move channel.cc channel.h to node directory; merge ns-3-tracing from mathieu

Tom Henderson 2007-03-18 14:06:51 -07:00
parent 79568bde6f
commit 327949573d
69 changed files with 3001 additions and 982 deletions

View File

@ -140,9 +140,15 @@ common.add_sources([
'tags.cc',
'pcap-writer.cc',
'trace-writer.cc',
'trace-container.cc',
'variable-tracer-test.cc',
'stream-tracer-test.cc',
'trace-context.cc',
'trace-resolver.cc',
'callback-trace-source.cc',
'empty-trace-resolver.cc',
'composite-trace-resolver.cc',
'trace-root.cc',
])
common.add_headers ([
])
common.add_inst_headers([
'buffer.h',
@ -150,14 +156,19 @@ common.add_inst_headers([
'trailer.h',
'tags.h',
'packet.h',
'ui-variable-tracer.h',
'si-variable-tracer.h',
'f-variable-tracer.h',
'callback-tracer.h',
'stream-tracer.h',
'uv-trace-source.h',
'sv-trace-source.h',
'fv-trace-source.h',
'trace-writer.h',
'trace-container.h',
'pcap-writer.h',
'callback-trace-source.h',
'trace-context.h',
'trace-resolver.h',
'empty-trace-resolver.h',
'composite-trace-resolver.h',
'array-trace-resolver.h',
'trace-root.h',
'terminal-trace-resolver.h',
])
node = build.Ns3Module ('node', 'src/node')
@ -193,6 +204,8 @@ node.add_sources ([
'net-device-list.cc',
'queue.cc',
'drop-tail.cc',
'channel.cc',
'node-list.cc',
])
node.add_headers ([
'ipv4-header.h',
@ -229,10 +242,12 @@ node.add_inst_headers ([
'arp-header.h',
'ipv4-header.h',
'udp-header.h',
'channel.h',
'node-list.h',
])
p2p = build.Ns3Module ('p2p', 'src/devices/p2p')
ns3.add (p2p)
#ns3.add (p2p)
p2p.add_deps (['node'])
p2p.add_sources ([
'p2p-net-device.cc',
@ -251,7 +266,6 @@ serial.add_sources ([
'serial-channel.cc',
'serial-phy.cc',
'layer-connector.cc',
'channel.cc',
])
serial.add_headers ([
'propagator.h',
@ -261,7 +275,6 @@ serial.add_inst_headers ([
'serial-channel.h',
'serial-phy.h',
'layer-connector.h',
'channel.h',
])
@ -312,7 +325,7 @@ sample_ptr.add_dep('core')
sample_ptr.add_source('main-ptr.cc')
sample_trace = build.Ns3Module('sample-trace', 'samples')
ns3.add(sample_trace)
#ns3.add(sample_trace)
sample_trace.add_dep('common')
sample_trace.set_executable()
sample_trace.add_source('main-trace.cc')
@ -349,7 +362,7 @@ sample_simple.add_source('main-simple.cc')
sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples')
sample_sp2p.set_executable()
ns3.add(sample_sp2p)
#n3.add(sample_sp2p)
sample_sp2p.add_deps(['core', 'simulator', 'node', 'p2p'])
sample_sp2p.add_source('main-simple-p2p.cc')

View File

@ -31,12 +31,15 @@
#include "ns3/serial-channel.h"
#include "ns3/serial-net-device.h"
#include "ns3/trace-writer.h"
#include "ns3/trace-container.h"
#include "ns3/drop-tail.h"
#include "ns3/arp-ipv4-interface.h"
#include "ns3/ipv4.h"
#include "ns3/trace-context.h"
#include "ns3/udp-socket.h"
#include "ns3/simulator.h"
#include "ns3/node-list.h"
#include "ns3/trace-root.h"
#include "ns3/pcap-writer.h"
using namespace ns3;
@ -61,27 +64,74 @@ public:
~Logger () {}
void Log (std::string const &name, const Packet &p)
void Log (TraceContext const &context, const Packet &p)
{
NS_DEBUG_UNCOND("**** LogEnque ("<< name << " " << &p << ")");
m_filestr << name << " " << &p << std::endl;
NodeList::NodeIndex nodeIndex;
context.Get (nodeIndex);
m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
Ipv4::InterfaceIndex interfaceIndex;
context.Get (interfaceIndex);
m_filestr << "interface=" << interfaceIndex << " ";
enum Queue::TraceType type;
context.Get (type);
switch (type)
{
case Queue::ENQUEUE:
m_filestr << "enqueue";
break;
case Queue::DEQUEUE:
m_filestr << "dequeue";
break;
case Queue::DROP:
m_filestr << "drop";
break;
}
m_filestr << " bytes=" << p.GetSize () << std::endl;
}
protected:
TraceWriter m_tracer;
};
static void
GenerateTraffic (UdpSocket *socket, uint32_t size)
{
std::cout << "Node: " << socket->GetNode()->GetId ()
<< " at=" << Simulator::Now ().GetSeconds () << "s,"
<< " tx bytes=" << size << std::endl;
socket->SendDummy (size);
if (size > 50)
{
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
}
}
static void
UdpSocketPrinter (UdpSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
{
std::cout << "Node: " << socket->GetNode()->GetId ()
<< " at=" << Simulator::Now ().GetSeconds () << "s,"
<< " rx bytes=" << size << std::endl;
}
static void
PrintTraffic (UdpSocket *socket)
{
socket->SetDummyRxCallback (MakeCallback (&UdpSocketPrinter));
}
int main (int argc, char *argv[])
{
NS_DEBUG_UNCOND("Serial Net Device Test");
TraceContainer traceContainerA;
TraceContainer traceContainerB;
// create two nodes and a simple SerialChannel
InternetNode a;
InternetNode b;
SerialChannel ch;
SerialChannel ch = SerialChannel ("Test Channel", 1000, Seconds (0.1));
NodeList::Add (&a);
NodeList::Add (&b);
// create two NetDevices and assign one to each node
// Note: this would normally be done also in conjunction with
@ -94,8 +144,7 @@ int main (int argc, char *argv[])
MacAddress addra("00:00:00:00:00:01");
SerialNetDevice neta(&a, addra);
DropTailQueue dtqa ("a");
dtqa.RegisterTraces (traceContainerA);
DropTailQueue dtqa;
neta.AddQueue(&dtqa);
neta.SetName("a.eth0");
@ -103,16 +152,15 @@ int main (int argc, char *argv[])
MacAddress addrb("00:00:00:00:00:02");
SerialNetDevice netb(&b, addrb);
DropTailQueue dtqb ("b");
dtqb.RegisterTraces (traceContainerB);
DropTailQueue dtqb;
netb.AddQueue(&dtqb);
netb.SetName("b.eth0");
// bind the two NetDevices together by using a simple Channel
// this method changed to do a bidirectional binding
ch.Attach(&neta);
ch.Attach(&netb);
neta.Attach (&ch);
netb.Attach (&ch);
// Some simple prints to see whether it is working
NS_DEBUG_UNCOND("neta.GetMtu() <= " << neta.GetMtu());
@ -153,6 +201,9 @@ int main (int argc, char *argv[])
NS_DEBUG_UNCOND("Setting ARP interface to UP");
arpipv4interfacep->SetUp();
a.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode b");
ArpIpv4Interface* arpipv4interfacepb = new ArpIpv4Interface(&b, &netb);
uint32_t indexB = (&b)->GetIpv4 ()->AddInterface (arpipv4interfacepb);
@ -170,20 +221,28 @@ int main (int argc, char *argv[])
NS_DEBUG_UNCOND("Setting ARP interface to UP");
arpipv4interfacepb->SetUp();
b.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);
UdpSocket *source = new UdpSocket (&a);
UdpSocket *sink = new UdpSocket(&b);
sink->Bind (80);
source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);
Logger logger("serial-net-test.log");
traceContainerA.SetCallback ("Queue::Enque",
MakeCallback (&Logger::Log, &logger));
TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*",
MakeCallback (&Logger::Log, &logger));
// create a packet on one node and send it through, reading it
// on the other node
Packet p;
PrintTraffic (sink);
GenerateTraffic (source, 100);
NS_DEBUG_UNCOND("Sending Packet " << &p);
arpipv4interfacep->Send(p, Ipv4Address("10.1.1.2"));
Simulator::Run ();
//neta.Send(p, MacAddress()); // Test that all-zero's MacAddress used
//netb.Send(p, "00:01:02:03:04:05"); // Dummy function call
Simulator::Destroy ();
delete source;
delete sink;
return 0;
}

View File

@ -9,10 +9,10 @@
using namespace ns3;
CallbackTracer<Packet> a;
CallbackTraceSourcer<Packet> a;
UiVariableTracer<unsigned short> b;
StreamTracer c;
CallbackTracer<double, int> d;
CallbackTraceSourcer<double, int> d;
void
RegisterAllTraceSources (TraceContainer *container)

View File

@ -48,6 +48,7 @@
#include "ns3/internet-node.h"
#include "ns3/serial-channel.h"
#include "ns3/serial-net-device.h"
#include "ns3/mac-address.h"
#include "ns3/ipv4-address.h"
#include "ns3/arp-ipv4-interface.h"
@ -60,6 +61,8 @@
#include "ns3/arp-header.h"
#include "ns3/ipv4-header.h"
#include "ns3/udp-header.h"
#include "ns3/node-list.h"
#include "ns3/trace-root.h"
using namespace ns3;
@ -81,23 +84,37 @@ public:
~Tracer () {};
void LogEnqueue (std::string const &name, const Packet &p)
void LogNodeInterface (TraceContext const &context)
{
m_filestr << name << " que ";
PrintLlcPacket (p, m_filestr);
NodeList::NodeIndex nodeIndex;
context.Get (nodeIndex);
m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
Ipv4::InterfaceIndex interfaceIndex;
context.Get (interfaceIndex);
m_filestr << "interface=" << interfaceIndex << " ";
}
void LogEnqueue (TraceContext const &context, const Packet &p)
{
LogNodeInterface (context);
m_filestr << " que p=" << p.GetUid ();
//PrintLlcPacket (p, m_filestr);
m_filestr << std::endl;
}
void LogDequeue (std::string const &name, const Packet &p)
void LogDequeue (TraceContext const &context, const Packet &p)
{
m_filestr << name << " deq ";
PrintLlcPacket (p, m_filestr);
LogNodeInterface (context);
m_filestr << " deq p=" << p.GetUid ();
//PrintLlcPacket (p, m_filestr);
m_filestr << std::endl;
}
void LogDrop (std::string const &name, const Packet &p)
void LogDrop (TraceContext const &context, const Packet &p)
{
m_filestr << name << " dro ";
PrintLlcPacket (p, m_filestr);
LogNodeInterface (context);
m_filestr << " dro p=" << p.GetUid ();
//PrintLlcPacket (p, m_filestr);
m_filestr << std::endl;
}
@ -199,7 +216,7 @@ PrintRoutingTable (InternetNode *a, std::string name)
static SerialChannel *
AddDuplexLink(
std::string &name,
std::string name,
uint64_t bps,
uint32_t delay,
InternetNode* a,
@ -207,12 +224,8 @@ AddDuplexLink(
const MacAddress& macaddra,
InternetNode* b,
const Ipv4Address& addrb,
const MacAddress& macaddrb,
// const Rate& rate,
// const Time& delay,
TraceContainer &traceContainer)
const MacAddress& macaddrb)
{
std::string qName;
SerialChannel* channel = new SerialChannel(name, bps, MilliSeconds(delay));
// Duplex link is assumed to be subnetted as a /30
@ -220,30 +233,24 @@ AddDuplexLink(
Ipv4Mask netmask("255.255.255.252");
assert(netmask.IsMatch(addra,addrb));
qName = name + "::Queue A";
DropTailQueue* dtqa = new DropTailQueue(qName);
dtqa->RegisterTraces (traceContainer);
DropTailQueue* dtqa = new DropTailQueue();
SerialNetDevice* neta = new SerialNetDevice(a, macaddra);
neta->AddQueue(dtqa);
Ipv4Interface *interfA = new ArpIpv4Interface (a, neta);
uint32_t indexA = a->GetIpv4 ()->AddInterface (interfA);
channel->Attach (neta);
neta->Attach (channel);
interfA->SetAddress (addra);
interfA->SetNetworkMask (netmask);
interfA->SetUp ();
qName = name + "::Queue B";
DropTailQueue* dtqb = new DropTailQueue(qName);
dtqb->RegisterTraces (traceContainer);
DropTailQueue* dtqb = new DropTailQueue();
SerialNetDevice* netb = new SerialNetDevice(b, macaddrb);
netb->AddQueue(dtqb);
Ipv4Interface *interfB = new ArpIpv4Interface (b, netb);
uint32_t indexB = b->GetIpv4 ()->AddInterface (interfB);
channel->Attach (netb);
netb->Attach (channel);
interfB->SetAddress (addrb);
@ -262,19 +269,6 @@ AddDuplexLink(
return channel;
}
static void
SetupTrace (TraceContainer &container, Tracer &tracer)
{
container.SetCallback ("Queue::Enqueue",
MakeCallback (&Tracer::LogEnqueue, &tracer));
container.SetCallback ("Queue::Dequeue",
MakeCallback (&Tracer::LogDequeue, &tracer));
container.SetCallback ("Queue::Drop",
MakeCallback (&Tracer::LogDrop, &tracer));
}
int main (int argc, char *argv[])
{
@ -295,37 +289,27 @@ int main (int argc, char *argv[])
InternetNode *n2 = new InternetNode();
InternetNode *n3 = new InternetNode();
TraceContainer traceContainer;
NodeList::Add (n0);
NodeList::Add (n1);
NodeList::Add (n2);
NodeList::Add (n3);
n0->SetName(std::string("Node 0"));
n1->SetName(std::string("Node 1"));
n2->SetName(std::string("Node 2"));
n3->SetName(std::string("Node 3"));
Tracer tracer("serial-net-test.log");
std::string channelName;
channelName = "Channel 1";
SerialChannel* ch1 = AddDuplexLink (channelName, 5000000, 2,
SerialChannel* ch1 = AddDuplexLink ("Channel 1", 5000000, 2,
n0, Ipv4Address("10.1.1.1"), MacAddress("00:00:00:00:00:01"),
n2, Ipv4Address("10.1.1.2"), MacAddress("00:00:00:00:00:02"),
traceContainer);
SetupTrace (traceContainer, tracer);
channelName = "Channel 2";
SerialChannel* ch2 = AddDuplexLink (channelName, 5000000, 2,
n2, Ipv4Address("10.1.1.2"), MacAddress("00:00:00:00:00:02"));
SerialChannel* ch2 = AddDuplexLink ("Channel 2", 5000000, 2,
n1, Ipv4Address("10.1.2.1"), MacAddress("00:00:00:00:00:03"),
n2, Ipv4Address("10.1.2.2"), MacAddress("00:00:00:00:00:04"),
traceContainer);
SetupTrace (traceContainer, tracer);
n2, Ipv4Address("10.1.2.2"), MacAddress("00:00:00:00:00:04"));
channelName = "Channel 3";
SerialChannel* ch3 = AddDuplexLink (channelName, 1500000, 10,
SerialChannel* ch3 = AddDuplexLink ("Channel 3", 1500000, 10,
n2, Ipv4Address("10.1.3.1"), MacAddress("00:00:00:00:00:05"),
n3, Ipv4Address("10.1.3.2"), MacAddress("00:00:00:00:00:06"),
traceContainer);
SetupTrace (traceContainer, tracer);
n3, Ipv4Address("10.1.3.2"), MacAddress("00:00:00:00:00:06"));
UdpSocket *source0 = new UdpSocket (n0);
UdpSocket *source3 = new UdpSocket (n3);
@ -341,6 +325,15 @@ int main (int argc, char *argv[])
n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
Tracer tracer("serial-net-test.log");
TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/enqueue",
MakeCallback (&Tracer::LogEnqueue, &tracer));
TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/dequeue",
MakeCallback (&Tracer::LogDequeue, &tracer));
TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/drop",
MakeCallback (&Tracer::LogDrop, &tracer));
PrintTraffic (sink3);
GenerateTraffic (source0, 100);

View File

@ -0,0 +1,138 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef ARRAY_TRACE_RESOLVER_H
#define ARRAY_TRACE_RESOLVER_H
#include <stdint.h>
#include <string>
#include "ns3/callback.h"
#include "trace-resolver.h"
namespace ns3 {
/**
* \brief a helper class to offer trace resolution for an array of objects.
* \ingroup tracing
*/
template <typename T>
class ArrayTraceResolver : public TraceResolver
{
public:
/**
* \brief array index trace context
*
* During namespace parsing, ns3::ArrayTraceResolver will
* embed an instance of this class in the TraceContext
* associated to every child object of the object stored
* at the index.
*
* The reason why this class exists is to ensure that we
* need to ensure that we can store a unique type as context
* into the TraceContext associated to this trace resolver.
*/
class Index
{
public:
Index ();
Index (uint32_t index);
/**
* The Index is automatically convertible to the
* uin32_t type such that it really behaves like a uint32_t
* array index for the user.
*
* \returns the index itself
*/
operator uint32_t ();
private:
uint32_t m_index;
};
/**
* \param context trace context associated to this trace resolver
* \param getSize callback which returns dynamically the size of underlying array
* \param get callback which returns any element in the underlying array
*
* Construct a trace resolver which can match any input integer
* against an element in an array. The array is accessed using a
* pair of callbacks. It is the responsability of the user to
* provide two such callbacks whose job is to adapt the array
* API to the resolver needs. Each element of the array is expected
* to provide a method named CreateTraceResolver which takes as
* only argument a reference to a const TraceContext and returns
* a pointer to a TraceResolver. i.e. the signature is:
* TraceResolver * (*) (TraceContext const &)
*/
ArrayTraceResolver (TraceContext const &context,
Callback<uint32_t> getSize,
Callback<T *, uint32_t> get);
private:
virtual TraceResolverList DoLookup (std::string id) const;
Callback<uint32_t> m_getSize;
Callback<T *, uint32_t> m_get;
};
}//namespace ns3
namespace ns3 {
template <typename T>
ArrayTraceResolver<T>::Index::Index ()
: m_index ()
{}
template <typename T>
ArrayTraceResolver<T>::Index::Index (uint32_t index)
: m_index (index)
{}
template <typename T>
ArrayTraceResolver<T>::Index::operator uint32_t ()
{
return m_index;
}
template <typename T>
ArrayTraceResolver<T>::ArrayTraceResolver (TraceContext const &context,
Callback<uint32_t> getSize,
Callback<T *, uint32_t> get)
: TraceResolver (context),
m_getSize (getSize),
m_get (get)
{}
template <typename T>
TraceResolver::TraceResolverList
ArrayTraceResolver<T>::DoLookup (std::string id) const
{
TraceResolverList list;
if (id == "*")
{
for (uint32_t i = 0; i < m_getSize (); i++)
{
TraceContext context = GetContext ();
typename ArrayTraceResolver<T>::Index index = typename ArrayTraceResolver<T>::Index (i);
context.Add (index);
list.push_back (m_get (i)->CreateTraceResolver (context));
}
}
return list;
}
}//namespace ns3
#endif /* ARRAY_TRACE_RESOLVER_H */

View File

@ -0,0 +1,95 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "callback-trace-source.h"
#include "ns3/test.h"
namespace ns3 {
class CallbackTraceSourceTest : public Test
{
public:
CallbackTraceSourceTest ();
virtual ~CallbackTraceSourceTest ();
virtual bool RunTests (void);
private:
void CbOne (TraceContext const &context, uint8_t a, double b);
void CbTwo (TraceContext const &context, uint8_t a, double b);
bool m_one;
bool m_two;
};
CallbackTraceSourceTest::CallbackTraceSourceTest ()
: Test ("CallbackTraceSource")
{}
CallbackTraceSourceTest::~CallbackTraceSourceTest ()
{}
void
CallbackTraceSourceTest::CbOne (TraceContext const &context, uint8_t a, double b)
{
m_one = true;
}
void
CallbackTraceSourceTest::CbTwo (TraceContext const &context, uint8_t a, double b)
{
m_two = true;
}
bool
CallbackTraceSourceTest::RunTests (void)
{
bool ok = true;
TraceContext ctx;
CallbackTraceSource<uint8_t,double> trace;
trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this), ctx);
trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this), ctx);
m_one = false;
m_two = false;
trace (1, 2);
if (!m_one || !m_two)
{
ok = false;
}
trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this));
m_one = false;
m_two = false;
trace (1, 2);
if (m_one || !m_two)
{
ok = false;
}
trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this));
m_one = false;
m_two = false;
trace (1, 2);
if (m_one || m_two)
{
ok = false;
}
return ok;
}
CallbackTraceSourceTest g_callbackTraceTest;
}//namespace ns3

View File

@ -0,0 +1,163 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006,2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CALLBACK_TRACE_H
#define CALLBACK_TRACE_H
#include <list>
#include "ns3/callback.h"
#include "ns3/fatal-error.h"
#include "trace-context.h"
namespace ns3 {
/**
* \brief log arbitrary number of parameters to a matching ns3::Callback
* \ingroup tracing
*
* Whenever operator () is invoked on this class, the call and its arguments
* are forwarded to the internal matching ns3::Callback.
*/
template<typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty>
class CallbackTraceSource {
public:
CallbackTraceSource ();
void AddCallback (CallbackBase const & callback, TraceContext const & context);
void RemoveCallback (CallbackBase const & callback);
void operator() (void);
void operator() (T1 a1);
void operator() (T1 a1, T2 a2);
void operator() (T1 a1, T2 a2, T3 a3);
void operator() (T1 a1, T2 a2, T3 a3, T4 a4);
private:
typedef std::list<Callback<void,TraceContext const &,T1,T2,T3,T4> > CallbackList;
TraceContext m_context;
CallbackList m_callbackList;
};
}; // namespace ns3
// implementation below.
namespace ns3 {
template<typename T1, typename T2,
typename T3, typename T4>
CallbackTraceSource<T1,T2,T3,T4>::CallbackTraceSource ()
: m_callbackList ()
{}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::AddCallback (CallbackBase const & callback,
TraceContext const &context)
{
Callback<void,TraceContext const &,T1,T2,T3,T4> cb;
if (!cb.CheckType (callback))
{
NS_FATAL_ERROR ("Incompatible callbacks. (feed to \"c++filt -t\"): got=\"" <<
typeid (callback).name () << "\" expected=\"" <<
typeid (cb).name () << "\"");
}
m_context.Add (context);
cb = *static_cast<Callback<void,TraceContext const &,T1,T2,T3,T4> const *> (&callback);
m_callbackList.push_back (cb);
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::RemoveCallback (CallbackBase const & callback)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); /* empty */)
{
if ((*i).IsEqual (callback))
{
i = m_callbackList.erase (i);
}
else
{
i++;
}
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (void)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1, a2);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1, a2, a3);
}
}
template<typename T1, typename T2,
typename T3, typename T4>
void
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3, T4 a4)
{
for (typename CallbackList::iterator i = m_callbackList.begin ();
i != m_callbackList.end (); i++)
{
(*i) (m_context, a1, a2, a3, a4);
}
}
}//namespace ns3
#endif /* CALLBACK_TRACE_H */

View File

@ -1,111 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef CALLBACK_TRACER_H
#define CALLBACK_TRACER_H
#include "ns3/callback.h"
namespace ns3 {
class CallbackTracerBase {
public:
virtual ~CallbackTracerBase () {}
bool CheckCallbackType (CallbackBase const&callback)
{
return CheckType (callback);
}
private:
virtual bool CheckType (CallbackBase const&callback) = 0;
};
/**
* \brief log arbitrary number of parameters to a matching ns3::Callback
*
* Whenever operator () is invoked on this class, the call and its arguments
* are forwarded to the internal matching ns3::Callback.
*/
template<typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty,
typename T5 = empty>
class CallbackTracer : public CallbackTracerBase {
public:
CallbackTracer ()
: m_callback () {}
void SetCallback (Callback<void,T1,T2,T3,T4,T5> callback)
{
m_callback = callback;
}
void operator() (void)
{
if (!m_callback.IsNull ())
{
m_callback ();
}
}
void operator() (T1 a1)
{
if (!m_callback.IsNull ())
{
m_callback (a1);
}
}
void operator() (T1 a1, T2 a2)
{
if (!m_callback.IsNull ())
{
m_callback (a1,a2);
}
}
void operator() (T1 a1, T2 a2, T3 a3)
{
if (!m_callback.IsNull ())
{
m_callback (a1,a2,a3);
}
}
void operator() (T1 a1, T2 a2, T3 a3, T4 a4)
{
if (!m_callback.IsNull ())
{
m_callback (a1,a2,a3,a4);
}
}
void operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5)
{
if (!m_callback.IsNull ())
{
m_callback (a1,a2,a3,a4,a5);
}
}
private:
virtual bool CheckType (CallbackBase const&callback)
{
return m_callback.CheckType (callback);
}
Callback<void,T1,T2,T3,T4,T5> m_callback;
};
}; // namespace ns3
#endif /* CALLBACK_TRACER_H */

View File

@ -0,0 +1,331 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "composite-trace-resolver.h"
namespace ns3 {
CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context)
: TraceResolver (context)
{}
CompositeTraceResolver::~CompositeTraceResolver ()
{}
void
CompositeTraceResolver::DoAdd (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
TraceContext const &context)
{
struct CallbackTraceSourceItem item;
item.name = name;
item.createResolver = createResolver;
item.context = context;
m_items.push_back (item);
}
TraceResolver::TraceResolverList
CompositeTraceResolver::DoLookup (std::string id) const
{
if (id == "*")
{
TraceResolver::TraceResolverList list;
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
{
list.push_back (i->createResolver (i->context));
}
return list;
}
std::string::size_type start, end;
start = id.find_first_of ("(", 0);
end = id.find_first_of (")", 0);
if (start != 0 || end != (id.size ()-1))
{
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
{
if (i->name == id)
{
TraceResolver::TraceResolverList list;
list.push_back (i->createResolver (i->context));
return list;
}
}
}
std::list<std::string> names;
std::string alternatives = std::string (id, start+1, end-1);
std::string::size_type next, cur;
next = 0;
cur = 0;
while (true)
{
std::string element;
next = alternatives.find ("|", cur);
if (next == std::string::npos)
{
element = std::string (alternatives, cur, alternatives.size ());
names.push_back (element);
break;
}
element = std::string (alternatives, cur, next);
names.push_back (element);
cur = next + 1;
}
TraceResolver::TraceResolverList list;
for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++)
{
for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++)
{
if (j->name == *i)
{
list.push_back (j->createResolver (j->context));
break;
}
}
}
return list;
}
}//namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
namespace ns3 {
class CompositeTraceResolverTest : public Test
{
public:
enum TraceSources {
TEST_TRACE_DOUBLEA,
TEST_TRACE_DOUBLEB,
TEST_TRACE_SUBRESOLVER,
};
enum SubTraceSources {
TEST_SUBTRACE_INT,
};
CompositeTraceResolverTest ();
virtual ~CompositeTraceResolverTest ();
virtual bool RunTests (void);
private:
void TraceDouble (TraceContext const &context, double v);
void TraceInt (TraceContext const &context, int v);
TraceResolver *CreateSubResolver (TraceContext const &context);
bool m_gotDoubleA;
bool m_gotDoubleB;
CallbackTraceSource<int> m_traceInt;
bool m_gotInt;
};
CompositeTraceResolverTest::CompositeTraceResolverTest ()
: Test ("CompositeTraceResolver")
{}
CompositeTraceResolverTest::~CompositeTraceResolverTest ()
{}
void
CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
{
enum CompositeTraceResolverTest::TraceSources source;
context.Get (source);
switch (source)
{
case TEST_TRACE_DOUBLEA:
m_gotDoubleA = true;
break;
case TEST_TRACE_DOUBLEB:
m_gotDoubleB = true;
break;
default:
NS_FATAL_ERROR ("should not get any other trace source in this sink");
break;
}
}
void
CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v)
{
m_gotInt = true;
}
TraceResolver *
CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context)
{
CompositeTraceResolver *subresolver = new CompositeTraceResolver (context);
subresolver->Add ("trace-int", m_traceInt, TEST_SUBTRACE_INT);
return subresolver;
}
bool
CompositeTraceResolverTest::RunTests (void)
{
bool ok = true;
CallbackTraceSource<double> traceDoubleA;
CallbackTraceSource<double> traceDoubleB;
TraceContext context;
CompositeTraceResolver resolver (context) ;
resolver.Add ("trace-double-a", traceDoubleA, TEST_TRACE_DOUBLEA);
resolver.Add ("trace-double-b", traceDoubleB, TEST_TRACE_DOUBLEB);
resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
if (!m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
m_gotDoubleA = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || !m_gotDoubleB)
{
ok = false;
}
m_gotDoubleA = false;
m_gotDoubleB = false;
resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Connect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
resolver.Connect ("/(trace-double-a)",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
resolver.Connect ("/(trace-double-a|trace-double-b)",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (!m_gotDoubleA || !m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/trace-double-a",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (m_gotDoubleA || !m_gotDoubleB)
{
ok = false;
}
resolver.Disconnect ("/(trace-double-a|trace-double-b)",
MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
m_gotDoubleA = false;
m_gotDoubleB = false;
traceDoubleA (0);
traceDoubleB (0);
if (m_gotDoubleA || m_gotDoubleB)
{
ok = false;
}
resolver.Add ("subresolver",
MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this),
TEST_TRACE_SUBRESOLVER);
resolver.Connect ("/subresolver/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (!m_gotInt)
{
ok = false;
}
resolver.Disconnect ("/subresolver/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (m_gotInt)
{
ok = false;
}
resolver.Connect ("/*/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (!m_gotInt)
{
ok = false;
}
resolver.Disconnect ("/subresolver/trace-int",
MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
m_gotInt = false;
m_traceInt (1);
if (m_gotInt)
{
ok = false;
}
return ok;
}
static CompositeTraceResolverTest g_compositeTraceResolverTest;
}//namespace ns3
#endif /* RUN_SELF_TESTS */

View File

@ -0,0 +1,211 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef COMPOSITE_TRACE_RESOLVER_H
#define COMPOSITE_TRACE_RESOLVER_H
#include "ns3/callback.h"
#include "trace-resolver.h"
#include "callback-trace-source.h"
#include "uv-trace-source.h"
#include "sv-trace-source.h"
#include "fv-trace-source.h"
#include "terminal-trace-resolver.h"
namespace ns3 {
/**
* \brief a helper class to aggregate contained TraceResolver and other trace sources.
* \ingroup tracing
*/
class CompositeTraceResolver : public TraceResolver
{
public:
CompositeTraceResolver (TraceContext const &context);
virtual ~CompositeTraceResolver ();
/**
* \param name name of trace source
* \param trace a callback trace source
* \param context the context associated to this trace source
*
* Add a callback trace source in this resolver. This trace
* source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T1, typename T2,
typename T3, typename T4,
typename T>
void Add (std::string name,
CallbackTraceSource<T1,T2,T3,T4> &trace, T const &context);
/**
* \param name name of trace source
* \param trace a signed variable trace source
* \param context the context associated to this trace source
*
* Add a signed variable trace source in this resolver.
* This trace source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T>
void Add (std::string name,
SVTraceSource<T> &trace, T const &context);
/**
* \param name name of trace source
* \param trace an unsigned variable trace source
* \param context the context associated to this trace source
*
* Add an unsigned variable trace source in this resolver.
* This trace source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T>
void Add (std::string name,
UVTraceSource<T> &trace, T const &context);
/**
* \param name name of trace source
* \param trace a floating-point variable trace source
* \param context the context associated to this trace source
*
* Add a floating-point variable trace source in this resolver.
* This trace source will match the name specified during namespace
* resolution. The TraceContext of this trace source will also
* be automatically extended to contain the input context.
*/
template <typename T>
void Add (std::string name,
FVTraceSource<T> &trace, T const &context);
/**
* \param name name of child trace resolver
* \param createResolver a trace resolver constructor
* \param context the context associated to this entry
*
* Add a child trace resolver to this resolver. This child
* trace resolver will match the name specified during
* namespace resolution. When this happens, the constructor
* will be invoked to create the child trace resolver and
* the associated TraceContext will be automatically extended
* to contain the input context.
*/
template <typename T>
void Add (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
T const &context);
private:
template <typename SOURCE, typename CONTEXT>
void DoAddTraceSource (std::string name,
SOURCE &traceSource, CONTEXT const &context);
template <typename SOURCE>
static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace,
TraceContext const &context);
void DoAdd (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
TraceContext const &context);
virtual TraceResolverList DoLookup (std::string id) const;
struct CallbackTraceSourceItem
{
std::string name;
Callback<TraceResolver *,TraceContext const &> createResolver;
TraceContext context;
};
typedef std::list<struct CallbackTraceSourceItem> TraceItems;
TraceItems m_items;
};
}//namespace ns3
namespace ns3 {
template <typename SOURCE, typename CONTEXT>
void
CompositeTraceResolver::DoAddTraceSource (std::string name,
SOURCE &traceSource, CONTEXT const &context)
{
TraceContext traceContext = GetContext ();
traceContext.Add (context);
TraceResolver *(*create) (SOURCE *trace, TraceContext const &context);
create = &CompositeTraceResolver::CreateTerminalTraceResolver<SOURCE>;
Callback<TraceResolver *,TraceContext const &> createResolver =
MakeBoundCallback (create, &traceSource);
DoAdd (name, createResolver, traceContext);
}
template <typename SOURCE>
TraceResolver *
CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource,
TraceContext const &context)
{
return new TerminalTraceResolver<SOURCE> (*traceSource, context);
}
template <typename T1, typename T2,
typename T3, typename T4,
typename T>
void
CompositeTraceResolver::Add (std::string name,
CallbackTraceSource<T1,T2,T3,T4> &trace,
T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
SVTraceSource<T> &trace, T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
UVTraceSource<T> &trace, T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
FVTraceSource<T> &trace, T const &context)
{
DoAddTraceSource (name, trace, context);
}
template <typename T>
void
CompositeTraceResolver::Add (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver,
T const &context)
{
TraceContext traceContext = GetContext ();
traceContext.Add (context);
DoAdd (name, createResolver, traceContext);
}
}//namespace ns3
#endif /* COMPOSITE_TRACE_RESOLVER_H */

View File

@ -0,0 +1,25 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "empty-trace-resolver.h"
ns3::EmptyTraceResolver::EmptyTraceResolver (TraceContext const &context)
: TraceResolver (context)
{}

View File

@ -0,0 +1,52 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EMPTY_TRACE_RESOLVER_H
#define EMPTY_TRACE_RESOLVER_H
#include "trace-resolver.h"
namespace ns3 {
class TraceContext;
/**
* \brief a TraceResolver instance which does not resolve anything.
* \ingroup tracing
*
* Trying to resolve against this class will yield no matches and no
* connections. Returning an instance of this class from a
* CreateTraceResolver method is a hand way of not implementing
* any Tracing code.
*/
class EmptyTraceResolver : public TraceResolver
{
public:
/**
* \param o necessary context for this class.
*
* The only constructor exported by this class.
*/
EmptyTraceResolver (TraceContext const &o);
};
}//namespace ns3
#endif /* EMPTY_TRACE_RESOLVER_H */

View File

@ -22,29 +22,32 @@
#ifndef F_VARIABLE_TRACER_H
#define F_VARIABLE_TRACER_H
#include "ns3/callback.h"
#include "callback-trace-source.h"
#include <stdint.h>
namespace ns3 {
class FVariableTracerBase {
class FVTraceSourceBase {
public:
typedef Callback<void,double, double> ChangeNotifyCallback;
typedef CallbackTraceSource<double, double> ChangeNotifyCallback;
FVariableTracerBase () {}
FVariableTracerBase (FVariableTracerBase const &o) {}
FVariableTracerBase &operator = (FVariableTracerBase const &o) {
FVTraceSourceBase () {}
FVTraceSourceBase (FVTraceSourceBase const &o) {}
FVTraceSourceBase &operator = (FVTraceSourceBase const &o) {
return *this;
}
~FVariableTracerBase () {}
~FVTraceSourceBase () {}
void setCallback(ChangeNotifyCallback callback) {
m_callback = callback;
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
m_callback.AddCallback (callback, context);
}
void RemoveCallback (CallbackBase const & callback) {
m_callback.RemoveCallback (callback);
}
protected:
void notify (double oldVal, double newVal) {
if (oldVal != newVal && !m_callback.IsNull ())
if (oldVal != newVal)
{
m_callback (oldVal, newVal);
}
@ -53,6 +56,11 @@ private:
ChangeNotifyCallback m_callback;
};
template <typename T>
class FVTraceSource : public FVTraceSourceBase
{
public:
};
}; // namespace ns3

View File

@ -19,32 +19,35 @@
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef SI_VARIABLE_TRACER_H
#define SI_VARIABLE_TRACER_H
#ifndef SV_TRACE_SOURCE_H
#define SV_TRACE_SOURCE_H
#include "ns3/callback.h"
#include "callback-trace-source.h"
#include <stdint.h>
namespace ns3 {
class SiVariableTracerBase {
class SVTraceSourceBase {
public:
typedef Callback<void,int64_t, int64_t> ChangeNotifyCallback;
typedef CallbackTraceSource<int64_t, int64_t> ChangeNotifyCallback;
SiVariableTracerBase () {}
SiVariableTracerBase (SiVariableTracerBase const &o) {}
SiVariableTracerBase &operator = (SiVariableTracerBase const &o) {
SVTraceSourceBase () {}
SVTraceSourceBase (SVTraceSourceBase const &o) {}
SVTraceSourceBase &operator = (SVTraceSourceBase const &o) {
return *this;
}
~SiVariableTracerBase () {}
~SVTraceSourceBase () {}
void SetCallback(ChangeNotifyCallback callback) {
m_callback = callback;
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
m_callback.AddCallback (callback, context);
}
void RemoveCallback (CallbackBase const & callback) {
m_callback.RemoveCallback (callback);
}
protected:
void Notify (int64_t oldVal, int64_t newVal) {
if (oldVal != newVal && !m_callback.IsNull ())
if (oldVal != newVal)
{
m_callback (oldVal, newVal);
}
@ -54,11 +57,12 @@ private:
};
template <typename T>
class UiVariableTracer;
class UVTraceSource;
/**
* \brief trace variables of type "signed integer"
* \ingroup tracing
*
* This template class implements a POD type: it
* behaves like any other variable of type "signed integer"
@ -67,12 +71,12 @@ class UiVariableTracer;
*
* To instantiate a 32-bit signed variable (to store
* a TCP counter for example), you would create a variable of type
* ns3::UiVariableTracer<int32_t> :
* ns3::UVTraceSource<int32_t> :
\code
#include <stdint.h>
#include "ns3/si-traced-variable.tcc"
#include "ns3/sv-trace-source.h"
ns3::SiVariableTracer<uint16_t> var;
ns3::SVTraceSource<uint16_t> var;
\endcode
* and you would use it like any other variable of type int32_t:
\code
@ -82,44 +86,44 @@ class UiVariableTracer;
\endcode
*/
template <typename T>
class SiVariableTracer : public SiVariableTracerBase {
class SVTraceSource : public SVTraceSourceBase {
public:
SiVariableTracer ()
SVTraceSource ()
: m_var (0)
{}
SiVariableTracer (T const &var)
SVTraceSource (T const &var)
: m_var (var)
{}
SiVariableTracer &operator = (SiVariableTracer const &o) {
SVTraceSource &operator = (SVTraceSource const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
SiVariableTracer &operator = (SiVariableTracer<TT> const &o) {
SVTraceSource &operator = (SVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
SiVariableTracer &operator = (UiVariableTracer<TT> const &o) {
SVTraceSource &operator = (UVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
SiVariableTracer &operator++ () {
SVTraceSource &operator++ () {
Assign (Get () + 1);
return *this;
}
SiVariableTracer &operator-- () {
SVTraceSource &operator-- () {
Assign (Get () - 1);
return *this;
}
SiVariableTracer operator++ (int) {
SiVariableTracer old (*this);
SVTraceSource operator++ (int) {
SVTraceSource old (*this);
++*this;
return old;
}
SiVariableTracer operator-- (int) {
SiVariableTracer old (*this);
SVTraceSource operator-- (int) {
SVTraceSource old (*this);
--*this;
return old;
}
@ -141,98 +145,98 @@ private:
};
template <typename T>
SiVariableTracer<T> &operator += (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator += (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () + rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator -= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator -= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () - rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator *= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator *= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () * rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator /= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator /= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () / rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator <<= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator <<= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () << rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator >>= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator >>= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () >> rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator &= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator &= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () & rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator |= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator |= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () | rhs.Get ());
return lhs;
}
template <typename T>
SiVariableTracer<T> &operator ^= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
SVTraceSource<T> &operator ^= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () ^ rhs.Get ());
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator += (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator += (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () + rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator -= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator -= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () - rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator *= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator *= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () * rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator /= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator /= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () / rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator <<= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator <<= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () << rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator >>= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator >>= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () >> rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator &= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator &= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () & rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator |= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator |= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () | rhs);
return lhs;
}
template <typename T, typename U>
SiVariableTracer<T> &operator ^= (SiVariableTracer<T> &lhs, U const &rhs) {
SVTraceSource<T> &operator ^= (SVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () ^ rhs);
return lhs;
}
}; // namespace ns3
#endif /* SI_VARIABLE_TRACER_H */
#endif /* SV_TRACE_SOURCE_H */

View File

@ -0,0 +1,66 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TERMINAL_TRACE_RESOLVER_H
#define TERMINAL_TRACE_RESOLVER_H
#include "trace-resolver.h"
namespace ns3 {
class TraceContext;
template <typename T>
class TerminalTraceResolver : public TraceResolver
{
public:
TerminalTraceResolver (T &traceSource, TraceContext const &context);
private:
virtual void DoConnect (CallbackBase const &cb);
virtual void DoDisconnect (CallbackBase const &cb);
T &m_traceSource;
};
}//namespace ns3
namespace ns3 {
template <typename T>
TerminalTraceResolver<T>::TerminalTraceResolver (T &traceSource,
TraceContext const &context)
: TraceResolver (context),
m_traceSource (traceSource)
{}
template <typename T>
void
TerminalTraceResolver<T>::DoConnect (CallbackBase const &cb)
{
m_traceSource.AddCallback (cb, GetContext ());
}
template <typename T>
void
TerminalTraceResolver<T>::DoDisconnect (CallbackBase const &cb)
{
m_traceSource.RemoveCallback (cb);
}
}//namespace ns3
#endif /* TERMINAL_TRACE_RESOLVER_H */

View File

@ -1,188 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-container.h"
#include "stream-tracer.h"
#include <utility>
#include "ns3/assert.h"
namespace ns3 {
TraceContainer::TraceContainer ()
{}
TraceContainer::~TraceContainer ()
{
m_uiList.erase (m_uiList.begin (), m_uiList.end ());
m_siList.erase (m_siList.begin (), m_siList.end ());
m_fList.erase (m_fList.begin (), m_fList.end ());
}
void
TraceContainer::SetUiVariableCallback (std::string const&name, Callback<void,uint64_t, uint64_t> callback)
{
for (UiListI i = m_uiList.begin (); i != m_uiList.end (); i++)
{
if ((*i).second == name)
{
(*i).first->SetCallback (callback);
return;
}
}
NS_ASSERT (false);
}
void
TraceContainer::SetSiVariableCallback (std::string const&name, Callback<void,int64_t, int64_t> callback)
{
for (SiListI i = m_siList.begin (); i != m_siList.end (); i++)
{
if ((*i).second == name)
{
(*i).first->SetCallback (callback);
return;
}
}
NS_ASSERT (false);
}
void
TraceContainer::SetFVariableCallback (std::string const&name, Callback<void,double, double> callback)
{
NS_ASSERT (false);
}
void
TraceContainer::SetStream (std::string const&name, std::ostream *os)
{
for (StreamTracerListI i = m_traceStreamList.begin (); i != m_traceStreamList.end (); i++)
{
if ((*i).second == name)
{
(*i).first->SetStream (os);
return;
}
}
NS_ASSERT (false);
}
void
TraceContainer::RegisterUiVariable (std::string const&name, UiVariableTracerBase *var)
{
// ensure unicity
for (UiListI i = m_uiList.begin (); i != m_uiList.end (); i++)
{
if (i->second == name)
{
m_uiList.erase (i);
break;
}
}
m_uiList.push_back (std::make_pair (var, name));
}
void
TraceContainer::RegisterSiVariable (std::string const&name, SiVariableTracerBase *var)
{
// ensure unicity
for (SiListI i = m_siList.begin (); i != m_siList.end (); i++)
{
if (i->second == name)
{
m_siList.erase (i);
break;
}
}
m_siList.push_back (std::make_pair (var, name));
}
void
TraceContainer::RegisterFVariable (std::string const&name, FVariableTracerBase *var)
{
NS_ASSERT (false);
}
void
TraceContainer::RegisterStream (std::string const&name, StreamTracer *stream)
{
// ensure unicity
for (StreamTracerListI i = m_traceStreamList.begin (); i != m_traceStreamList.end (); i++)
{
if (i->second == name)
{
m_traceStreamList.erase (i);
break;
}
}
m_traceStreamList.push_back (std::make_pair (stream,name));
}
void
TraceContainer::RegisterCallback (std::string const&name, CallbackTracerBase *tracer)
{
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
if (i->second == name)
{
m_callbackList.erase (i);
break;
}
}
m_callbackList.push_back (std::make_pair (tracer, name));
}
}; // namespace ns3
#include <iostream>
void
ns3::TraceContainer::PrintDebug (void)
{
if (!m_uiList.empty ())
{
std::cout << "ui var: " << std::endl;
for (UiListI i = m_uiList.begin (); i != m_uiList.end (); i++)
{
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_siList.empty ())
{
std::cout << "si var: " << std::endl;
for (SiListI i = m_siList.begin (); i != m_siList.end (); i++)
{
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_fList.empty ())
{
std::cout << "f var: " << std::endl;
for (FListI i = m_fList.begin (); i != m_fList.end (); i++)
{
std::cout << " \"" << (*i).second << "\""<<std::endl;
}
}
if (!m_callbackList.empty ())
{
std::cout << "callback list: "<<std::endl;
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
std::cout << " \"" << i->second << "\""<<std::endl;
}
}
}

View File

@ -1,312 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_CONTAINER_H
#define TRACE_CONTAINER_H
#include "ui-variable-tracer.h"
#include "si-variable-tracer.h"
#include "f-variable-tracer.h"
#include "callback-tracer.h"
#include "ns3/callback.h"
#include <list>
#include <string>
namespace ns3 {
class StreamTracer;
/**
* \brief register every source of trace events
*
* Model authors use the TraceContainer class to register
* their trace event sources. Model users use the TraceContainer
* class to connect their trace event listeners to the
* model trace event sources.
*
* TraceContainer can be used to register the following event sources:
* - ns3::StreamTracer : can be connected to any std::ostream
* - ns3::CallbackTracer: can be connected to any ns3::Callback
* - ns3::UiVariableTracer
* - ns3::SiVariableTracer
* - ns3::FVariableTracer
*
* The following sample code shows how you can:
* - create trace event sources
* - register the trace event sources in a trace container
* - set event sinks to each event source
*
* \include samples/main-trace.cc
*/
class TraceContainer {
public:
TraceContainer ();
~TraceContainer ();
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are variables of any unsigned
* integer type.
*/
void SetUiVariableCallback (std::string const &name,
Callback<void,uint64_t, uint64_t> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are variables of any signed
* integer type.
*/
void SetSiVariableCallback (std::string const &name, Callback<void,int64_t, int64_t> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source
*
* This method targets only event sources which are variables of any double type.
*/
void SetFVariableCallback (std::string const &name, Callback<void,double, double> callback);
/**
* \param name the name of the target event source
* \param os the output stream being connected to the source trace stream
*
* This method targets only event sources which are of type StreamTracer.
*/
void SetStream (std::string const &name, std::ostream *os);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackTracer<T1>
*/
template <typename T1>
void SetCallback (std::string const &name, Callback<void,T1> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackTracer<T1,T2>
*/
template <typename T1, typename T2>
void SetCallback (std::string const &name, Callback<void,T1,T2> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackTracer<T1,T2,T3>
*/
template <typename T1, typename T2, typename T3>
void SetCallback (std::string const &name, Callback<void,T1,T2,T3> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackTracer<T1,T2,T3,T4>
*/
template <typename T1, typename T2, typename T3, typename T4>
void SetCallback (std::string const&name, Callback<void,T1,T2,T3,T4> callback);
/**
* \param name the name of the target event source
* \param callback the callback being connected to the target event source.
*
* This method targets only event sources which are of type CallbackTracer<T1,T2,T3,T4,T5>
*/
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void SetCallback (std::string const &name, Callback<void,T1,T2,T3,T4,T5> callback);
/**
* \param name the name of the registered event source
* \param var the event source being registered
*
* This method registers only event sources of type "unsigned integer".
*/
void RegisterUiVariable (std::string const&name, UiVariableTracerBase *var);
/**
* \param name the name of the registered event source
* \param var the event source being registered
*
* This method registers only event sources of type "signed integer".
*/
void RegisterSiVariable (std::string const&name, SiVariableTracerBase *var);
/**
* \param name the name of the registered event source
* \param var the event source being registered
*
* This method registers only event sources of type "double".
*/
void RegisterFVariable (std::string const&name, FVariableTracerBase *var);
/**
* \param name the name of the registered event source
* \param stream the event source being registered
*
* This method registers only event sources of type StreamTracer.
*/
void RegisterStream (std::string const&name, StreamTracer *stream);
/**
* \param name the name of the registeref event source
* \param tracer the callback tracer being registered.
*
* This method registers only event sources of type CallbackTracer
*/
void RegisterCallback (std::string const&name, CallbackTracerBase*tracer);
/**
* Print the list of registered event sources in this container only.
*/
void PrintDebug (void);
private:
typedef std::list<std::pair<UiVariableTracerBase *, std::string> > UiList;
typedef std::list<std::pair<UiVariableTracerBase *, std::string> >::iterator UiListI;
typedef std::list<std::pair<SiVariableTracerBase *, std::string> > SiList;
typedef std::list<std::pair<SiVariableTracerBase *, std::string> >::iterator SiListI;
typedef std::list<std::pair<FVariableTracerBase *, std::string> > FList;
typedef std::list<std::pair<FVariableTracerBase *, std::string> >::iterator FListI;
typedef std::list<std::pair<StreamTracer *, std::string> > StreamTracerList;
typedef std::list<std::pair<StreamTracer *, std::string> >::iterator StreamTracerListI;
typedef std::list<std::pair<CallbackTracerBase *, std::string> > CallbackList;
typedef std::list<std::pair<CallbackTracerBase *, std::string> >::iterator CallbackListI;
UiList m_uiList;
SiList m_siList;
FList m_fList;
StreamTracerList m_traceStreamList;
CallbackList m_callbackList;
};
}; // namespace ns3
#include "ns3/assert.h"
namespace ns3 {
template <typename T1>
void
TraceContainer::SetCallback (std::string const&name, Callback<void,T1> callback)
{
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
if (i->second == name)
{
if (i->first->CheckCallbackType (callback))
{
static_cast<CallbackTracer<T1> *> (i->first)->SetCallback (callback);
return;
}
else
{
NS_ASSERT (!"non-matching callback");
}
}
}
NS_ASSERT (false);
}
template <typename T1, typename T2>
void
TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2> callback)
{
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
if (i->second == name)
{
if (i->first->CheckCallbackType (callback))
{
static_cast<CallbackTracer<T1,T2> *> (i->first)->SetCallback (callback);
return;
}
else
{
NS_ASSERT (!"non-matching callback");
}
}
}
NS_ASSERT (false);
}
template <typename T1, typename T2, typename T3>
void
TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2,T3> callback)
{
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
if (i->second == name)
{
if (i->first->CheckCallbackType (callback))
{
static_cast<CallbackTracer<T1,T2,T3> *> (i->first)->SetCallback (callback);
return;
}
else
{
NS_ASSERT (!"non-matching callback");
}
}
}
NS_ASSERT (false);
}
template <typename T1, typename T2, typename T3, typename T4>
void
TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2,T3,T4> callback)
{
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
if (i->second == name)
{
if (i->first->CheckCallbackType (callback))
{
static_cast<CallbackTracer<T1,T2,T3,T4> *> (i->first)->SetCallback (callback);
return;
}
else
{
NS_ASSERT (!"non-matching callback");
}
}
}
NS_ASSERT (false);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void
TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2,T3,T4,T5> callback)
{
for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++)
{
if (i->second == name)
{
if (i->first->CheckCallbackType (callback))
{
static_cast<CallbackTracer<T1,T2,T3,T4,T5> *> (i->first)->SetCallback (callback);
return;
}
else
{
NS_ASSERT (!"non-matching callback");
}
}
}
NS_ASSERT (false);
}
}; // namespace ns3
#endif /* TRACED_VARIABLE_CONTAINER_H */

320
src/common/trace-context.cc Normal file
View File

@ -0,0 +1,320 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-context.h"
#include "ns3/assert.h"
namespace ns3 {
std::vector<uint8_t> TraceContext::m_sizes;
TraceContext::TraceContext ()
: m_data (0)
{}
TraceContext::TraceContext (TraceContext const &o)
: m_data (o.m_data)
{
if (m_data != 0)
{
m_data->count++;
}
}
TraceContext const &
TraceContext::operator = (TraceContext const &o)
{
if (m_data != 0)
{
m_data->count--;
if (m_data->count == 0)
{
uint8_t *buffer = (uint8_t *)m_data;
delete [] buffer;
}
}
m_data = o.m_data;
if (m_data != 0)
{
m_data->count++;
}
return *this;
}
TraceContext::~TraceContext ()
{
if (m_data != 0)
{
m_data->count--;
if (m_data->count == 0)
{
uint8_t *buffer = (uint8_t *)m_data;
delete [] buffer;
}
}
}
uint8_t
TraceContext::GetSize (uint8_t uid)
{
return m_sizes[uid];
}
void
TraceContext::Add (TraceContext const &o)
{
if (o.m_data == 0)
{
return;
}
uint8_t currentUid;
uint16_t i = 0;
while (i < o.m_data->size)
{
currentUid = o.m_data->data[i];
uint8_t size = TraceContext::GetSize (currentUid);
uint8_t *selfBuffer = CheckPresent (currentUid);
uint8_t *otherBuffer = &(o.m_data->data[i+1]);
if (selfBuffer != 0)
{
if (memcmp (selfBuffer, otherBuffer, size) != 0)
{
NS_FATAL_ERROR ("You cannot add TraceContexts which "<<
"have different values stored in them.");
}
}
else
{
DoAdd (currentUid, otherBuffer);
}
i += 1 + size;
}
}
uint8_t *
TraceContext::CheckPresent (uint8_t uid) const
{
if (m_data == 0)
{
return false;
}
uint8_t currentUid;
uint16_t i = 0;
do {
currentUid = m_data->data[i];
uint8_t size = TraceContext::GetSize (currentUid);
if (currentUid == uid)
{
return &m_data->data[i+1];
}
i += 1 + size;
} while (i < m_data->size && currentUid != 0);
return 0;
}
bool
TraceContext::DoAdd (uint8_t uid, uint8_t const *buffer)
{
NS_ASSERT (uid != 0);
uint8_t size = TraceContext::GetSize (uid);
uint8_t *present = CheckPresent (uid);
if (present != 0) {
if (memcmp (present, buffer, size) == 0)
{
return true;
}
else
{
return false;
}
}
if (m_data == 0)
{
uint16_t newSize = 1 + size;
uint16_t allocatedSize;
if (newSize > 4)
{
allocatedSize = sizeof (struct Data) + newSize - 4;
}
else
{
allocatedSize = sizeof (struct Data);
}
struct Data *data = (struct Data *) (new uint8_t [allocatedSize] ());
data->size = newSize;
data->count = 1;
data->data[0] = uid;
memcpy (data->data + 1, buffer, size);
m_data = data;
}
else
{
uint16_t newSize = m_data->size + 1 + size;
uint16_t allocatedSize;
if (newSize > 4)
{
allocatedSize = sizeof (struct Data) + newSize - 4;
}
else
{
allocatedSize = sizeof (struct Data);
}
struct Data *data = (struct Data *) (new uint8_t [allocatedSize] ());
data->size = newSize;
data->count = 1;
memcpy (data->data, m_data->data, m_data->size);
data->data[m_data->size] = uid;
memcpy (data->data + m_data->size + 1, buffer, size);
m_data->count--;
if (m_data->count == 0)
{
uint8_t *buffer = (uint8_t *)m_data;
delete [] buffer;
}
m_data = data;
}
return true;
}
bool
TraceContext::DoGet (uint8_t uid, uint8_t *buffer) const
{
if (m_data == 0)
{
return false;
}
uint8_t currentUid;
uint16_t i = 0;
do {
currentUid = m_data->data[i];
uint8_t size = TraceContext::GetSize (currentUid);
if (currentUid == uid)
{
memcpy (buffer, &m_data->data[i+1], size);
return true;
}
i += 1 + size;
} while (i < m_data->size && currentUid != 0);
return false;
}
uint8_t
TraceContext::DoGetNextUid (void)
{
static uint8_t uid = 0;
if (uid == 0)
{
m_sizes.push_back (0);
}
uid++;
return uid;
}
}//namespace ns3
#include "ns3/test.h"
namespace ns3 {
template <int N>
class Ctx
{
public:
Ctx () : m_v (0) {}
Ctx (int v) : m_v (v) {}
int Get (void) const { return N;}
private:
int m_v;
};
class TraceContextTest : public Test
{
public:
TraceContextTest ();
virtual bool RunTests (void);
};
TraceContextTest::TraceContextTest ()
: Test ("TraceContext")
{}
bool
TraceContextTest::RunTests (void)
{
bool ok = true;
TraceContext ctx;
Ctx<0> v0;
Ctx<0> v01 = Ctx<0> (1);
Ctx<1> v1;
Ctx<2> v2;
Ctx<3> v3;
if (ctx.SafeGet (v0))
{
ok = false;
}
ctx.Add (v0);
ctx.Add (v0);
if (ctx.SafeAdd (v01))
{
ok = false;
}
ctx.Get (v0);
ctx.Add (v1);
ctx.Get (v1);
ctx.Get (v0);
ctx.Get (v1);
TraceContext copy = ctx;
ctx.Get (v0);
ctx.Get (v1);
copy.Get (v0);
copy.Get (v1);
copy.Add (v2);
copy.Get (v0);
copy.Get (v1);
copy.Get (v2);
ctx.Add (v3);
ctx.Get (v0);
ctx.Get (v1);
ctx.Get (v3);
if (ctx.SafeGet (v2))
{
ok = false;
}
if (copy.SafeGet (v3))
{
ok = false;
}
ctx.Add (copy);
ctx.Get (v2);
if (copy.SafeGet (v3))
{
ok = false;
}
copy.Add (ctx);
copy.Get (v3);
return ok;
}
static TraceContextTest g_traceContextTest;
}//namespace ns3

167
src/common/trace-context.h Normal file
View File

@ -0,0 +1,167 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_CONTEXT_H
#define TRACE_CONTEXT_H
#include <stdint.h>
#include <vector>
#include "ns3/fatal-error.h"
namespace ns3 {
/**
* \brief Provide context to trace sources
* \ingroup tracing
*
* Instances of this class are used to hold context
* for each trace source. Each instance holds a list of
* 'contexts'. Trace sinks can lookup these contexts
* from this list with the ns3::TraceContext::Get method.
*
* This class is implemented
* using Copy On Write which means that copying unmodified
* versions of this class is very cheap. However, modifying
* the content of this class through a call
* to ns3::TraceContext::Add will trigger a costly memory
* reallocation if needed.
*/
class TraceContext
{
public:
TraceContext ();
TraceContext (TraceContext const &o);
TraceContext const & operator = (TraceContext const &o);
~TraceContext ();
/**
* \param context add context to list of trace contexts.
*/
template <typename T>
void Add (T const &context);
/**
* \param o the other context
*
* Perform the Union operation (in the sense of set theory) on the
* two input lists of elements. This method is used in the
* ns3::CallbackTraceSourceSource class when multiple sinks are connected
* to a single source to ensure that the source does not need
* to store a single TraceContext instance per connected sink.
* Instead, all sinks share the same TraceContext.
*/
void Add (TraceContext const &o);
/**
* \param context context to get from this list of trace contexts.
*
* This method cannot fail. If the requested trace context is not
* stored in this TraceContext, then, the program will halt.
*/
template <typename T>
void Get (T &context) const;
private:
friend class TraceContextTest;
// used exclusively for testing code.
template <typename T>
bool SafeGet (T &context) const;
template <typename T>
bool SafeAdd (T &context);
template <typename T>
static uint8_t GetUid (void);
template <typename T>
static uint8_t GetNextUid (void);
static uint8_t DoGetNextUid (void);
static uint8_t GetSize (uint8_t uid);
uint8_t *CheckPresent (uint8_t uid) const;
bool DoAdd (uint8_t uid, uint8_t const *buffer);
bool DoGet (uint8_t uid, uint8_t *buffer) const;
static std::vector<uint8_t> m_sizes;
struct Data {
uint16_t count;
uint16_t size;
uint8_t data[4];
} * m_data;
};
}//namespace ns3
namespace ns3 {
template <typename T>
void
TraceContext::Add (T const &context)
{
uint8_t *data = (uint8_t *) &context;
bool ok = DoAdd (TraceContext::GetUid<T> (), data);
if (!ok)
{
NS_FATAL_ERROR ("Trying to add twice the same type with different values is invalid.");
}
}
template <typename T>
void
TraceContext::Get (T &context) const
{
uint8_t *data = (uint8_t *) &context;
bool found = DoGet (TraceContext::GetUid<T> (), data);
if (!found)
{
NS_FATAL_ERROR ("Type not stored in TraceContext");
}
}
template <typename T>
bool
TraceContext::SafeGet (T &context) const
{
uint8_t *data = (uint8_t *) &context;
bool found = DoGet (TraceContext::GetUid<T> (), data);
return found;
}
template <typename T>
bool
TraceContext::SafeAdd (T &context)
{
uint8_t *data = (uint8_t *) &context;
bool ok = DoAdd (TraceContext::GetUid<T> (), data);
return ok;
}
template <typename T>
uint8_t
TraceContext::GetUid (void)
{
static uint8_t uid = GetNextUid<T> ();
return uid;
}
template <typename T>
uint8_t
TraceContext::GetNextUid (void)
{
uint8_t uid = DoGetNextUid ();
m_sizes.push_back (sizeof (T));
return uid;
}
}//namespace ns3
#endif /* TRACE_CONTEXT_H */

View File

@ -0,0 +1,104 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-resolver.h"
namespace ns3 {
TraceResolver::TraceResolver (TraceContext const &context)
: m_context (context)
{}
TraceResolver::~TraceResolver ()
{}
TraceContext const &
TraceResolver::GetContext (void) const
{
return m_context;
}
void
TraceResolver::Connect (std::string path, CallbackBase const &cb)
{
std::string::size_type cur = 1;
// check that first char is "/"
std::string::size_type next = path.find ("/", cur);
std::string element = std::string (path, cur, next-1);
TraceResolverList resolverList = DoLookup (element);
for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
{
TraceResolver *resolver = *i;
if (next == std::string::npos)
{
// we really break the recursion here.
resolver->DoConnect (cb);
}
else
{
std::string subpath = std::string (path, next, std::string::npos);
resolver->Connect (subpath, cb);
}
delete resolver;
}
resolverList.erase (resolverList.begin (), resolverList.end ());
}
void
TraceResolver::Disconnect (std::string path, CallbackBase const &cb)
{
std::string::size_type cur = 1;
// check that first char is "/"
std::string::size_type next = path.find ("/", cur);
std::string element = std::string (path, cur, next-1);
TraceResolverList resolverList = DoLookup (element);
for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
{
TraceResolver *resolver = *i;
if (next == std::string::npos)
{
// we really break the recursion here.
resolver->DoDisconnect (cb);
}
else
{
std::string subpath = std::string (path, next, std::string::npos);
resolver->Disconnect (subpath, cb);
}
delete resolver;
}
resolverList.erase (resolverList.begin (), resolverList.end ());
}
TraceResolver::TraceResolverList
TraceResolver::DoLookup (std::string id) const
{
return TraceResolverList ();
}
void
TraceResolver::DoConnect (CallbackBase const &cb)
{}
void
TraceResolver::DoDisconnect (CallbackBase const &cb)
{}
}//namespace ns3

119
src/common/trace-resolver.h Normal file
View File

@ -0,0 +1,119 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_RESOLVER_H
#define TRACE_RESOLVER_H
#include <string>
#include <list>
#include "trace-context.h"
namespace ns3 {
class CallbackBase;
/**
* \brief the base class which is used to incremental perform trace
* namespace resolution.
* \ingroup tracing
*
* This class provides a public API to the ns3::TraceRoot object:
* - ns3::TraceResolver::Connect
* - ns3::TraceResolver::Disconnect
*
* It also provides an API for its subclasses. Each subclass should
* implement one of:
* - ns3::TraceResolver::DoLookup
* - ns3::TraceResolver::DoConnect and ns3::TraceResolver::DoDisconnect
* Each subclass must also provide an ns3::TraceContext to the TraceResolver
* constructor. Finally, each subclass can access the ns3::TraceContext
* associated to this ns3::TraceResolver through the
* ns3::TraceResolver::GetContext method.
*/
class TraceResolver
{
public:
virtual ~TraceResolver ();
/**
* \param path the namespace path to resolver
* \param cb the callback to connect to the matching namespace
*
* This method is typically invoked by ns3::TraceRoot but advanced
* users could also conceivably call it directly if they want to
* skip the ns3::TraceRoot.
*/
void Connect (std::string path, CallbackBase const &cb);
/**
* \param path the namespace path to resolver
* \param cb the callback to disconnect in the matching namespace
*
* This method is typically invoked by ns3::TraceRoot but advanced
* users could also conceivably call it directly if they want to
* skip the ns3::TraceRoot.
*/
void Disconnect (std::string path, CallbackBase const &cb);
protected:
/**
* \param context the context used to initialize this TraceResolver.
*
* Every subclass must call this constructor
*/
TraceResolver (TraceContext const &context);
/**
* \returns the ns3::TraceContext stored in this ns3::TraceResolver.
*
* Subclasses usually invoke this method to get access to the
* TraceContext stored here to pass it down to the TraceResolver
* constructors invoked from within the DoLookup method.
*/
TraceContext const &GetContext (void) const;
typedef std::list<TraceResolver *> TraceResolverList;
private:
TraceResolver ();
/**
* \param id the id to resolve. This is supposed to be
* one element of the global tracing namespace.
* \returns a list of reslvers which match the input namespace element
*
* A subclass which overrides this method should return a potentially
* empty list of pointers to ns3::TraceResolver instances which match
* the input namespace element. Each of these TraceResolver should be
* instanciated with a TraceContext which holds enough context
* information to identify the type of the TraceResolver.
*/
virtual TraceResolverList DoLookup (std::string id) const;
/**
* \param cb callback to connect
*
* This method is invoked on leaf trace resolvers.
*/
virtual void DoConnect (CallbackBase const &cb);
/**
* \param cb callback to disconnect
*
* This method is invoked on leaf trace resolvers.
*/
virtual void DoDisconnect (CallbackBase const &cb);
TraceContext m_context;
};
}//namespace ns3
#endif /* TRACE_RESOLVER_H */

54
src/common/trace-root.cc Normal file
View File

@ -0,0 +1,54 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "trace-root.h"
#include "ns3/composite-trace-resolver.h"
#include "ns3/trace-context.h"
namespace ns3 {
void
TraceRoot::Connect (std::string path, CallbackBase const &cb)
{
TraceResolver *resolver = GetComposite ();
resolver->Connect (path, cb);
}
void
TraceRoot::Disconnect (std::string path, CallbackBase const &cb)
{
TraceResolver *resolver = GetComposite ();
resolver->Disconnect (path, cb);
}
void
TraceRoot::Register (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver)
{
CompositeTraceResolver *resolver = GetComposite ();
resolver->Add (name, createResolver, TraceRoot::NOTHING);
}
CompositeTraceResolver *
TraceRoot::GetComposite (void)
{
static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ());
return &resolver;
}
} // namespace ns3

255
src/common/trace-root.h Normal file
View File

@ -0,0 +1,255 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TRACE_ROOT_H
#define TRACE_ROOT_H
#include <string>
#include "ns3/callback.h"
/**
* \defgroup tracing Tracing
*
* The low-level tracing framework is built around a few very simple
* concepts:
* - There can be any number of trace source objects. Each trace source
* object can generate any number of trace events. The current
* trace source objects are: ns3::CallbackTraceSourceSource, ns3::UVTraceSource,
* ns3::SVTraceSource, and, ns3::FVTraceSource.
* - Each trace source can be connected to any number of trace sinks.
* A trace sink is a ns3::Callback with a very special signature. Its
* first argument is always a ns3::TraceContext.
* - Every trace source is uniquely identified by a ns3::TraceContext. Every
* trace sink can query a ns3::TraceContext for information. This allows
* a trace sink which is connected to multiple trace sources to identify
* from which source each event is coming from.
*
* To allow the user to connect his own trace sinks to each trace source
* defined by any of the models he is using, the tracing framework defines
* a hierarchical namespace. The root of this namespace is accessed through
* the ns3::TraceRoot class. The namespace is represented as a string made
* of multiple elements, each of which is separated from the other elements
* by the '/' character. A namespace string always starts with a '/'.
*
* By default, the simulation models provide a '/nodes' tracing root. This
* '/nodes' namespace is structured as follows:
* \code
* /nodes/n/udp
* /nodes/n/ipv4
* /tx
* /rx
* /drop
* /interfaces/n/netdevice
* (NetDevice only) /queue/
* /enque
* /deque
* /drop
* /nodes/n/arp
* \endcode
*
* The 'n' element which follows the /nodes and /interfaces namespace elements
* identify a specific node and interface through their index within the
* ns3::NodeList and ns3::Ipv4 objects respectively.
*
* To connect a trace sink to a trace source identified by a namespace string,
* a user can call the ns3::TraceRoot::Connect method (the ns3::TraceRoot::Disconnect
* method does the symmetric operation). This connection method can accept
* fully-detailed namespace strings but it can also perform pattern matching
* on the user-provided namespace strings to connect multiple trace sources
* to a single trace sink in a single connection operation.
*
* The syntax of the pattern matching rules are loosely based on regular
* expressions:
* - the '*' character matches every element
* - the (a|b) construct matches element 'a' or 'b'
* - the [ss-ee] construct matches all numerical values which belong
* to the interval which includes ss and ee
*
* For example, the user could use the following to connect a single sink
* to the ipv4 tx, rx, and drop trace events:
*
* \code
* void MyTraceSink (TraceContext const &context, Packet &packet);
* TraceRoot::Connect ("/nodes/ * /ipv4/ *", MakeCallback (&MyTraceSink));
* \endcode
*
* Of course, this code would work only if the signature of the trace sink
* is exactly equal to the signature of all the trace sources which match
* the namespace string (if one of the matching trace source does not match
* exactly, a fatal error will be triggered at runtime during the connection
* process). The ns3::TraceContext extra argument contains
* information on where the trace source is located in the namespace tree.
* In that example, if there are multiple nodes in this scenario, each
* call to the MyTraceSink function would receive a different TraceContext,
* each of which would contain a different NodeList::Index object.
*
* It is important to understand exactly what an ns3::TraceContext
* is. It is a container for a number of type instances. Each instance of
* a ns3::TraceContext contains one and only one instance of a given type.
* ns3::TraceContext::Add can be called to add a type instance into a
* TraceContext instance and ns3::TraceContext::Get can be called to get
* a copy of a type instance stored into the ns3::TraceContext. If ::Get
* cannot retrieve the requested type, a fatal error is triggered at
* runtime. The values stored into an ns3::TraceContext attached to a
* trace source are automatically determined during the namespace
* resolution process. To retrieve a value from a ns3::TraceContext, the
* code can be as simple as this:
* \code
* void MyTraceSink (TraceContext const &context, Packet &packet)
* {
* NodeList::Index index;
* context.Get (index);
* std::cout << "node id=" << NodeList::GetNode (index)->GetId () << std::endl;
* }
* \endcode
*
* To define new trace sources, a model author needs to instante one trace source
* object for each kind of tracing event he wants to export. The trace source objects
* currently defined are:
* - ns3::CallbackTraceSourceSource: this trace source can be used to convey any kind of
* trace event to the user. It is a functor, that is, it is a variable
* which behaves like a function which will forward every event to every
* connected trace sink (i.e., ns3::Callback). This trace source takes
* up to four arguments and forwards these 4 arguments together with the
* ns3::TraceContext which identifies this trace source to the connected
* trace sinks.
* - ns3::UVTraceSource: this trace source is used to convey key state variable
* changes to the user. It behaves like a normal integer unsigned variable:
* you can apply every normal arithmetic operator to it. It will forward
* every change in the value of the variable back to every connected trace
* sink by providing a TraceContext, the old value and the new value.
* - ns3::SVTraceSource: this is the signed integer equivalent of
* ns3::UVTraceSource.
* - ns3::FVTraceSource: this is the floating point equivalent of
* ns3::UVTraceSource and ns3::SVTraceSource.
*
* Once the model author has instantiated these objects and has wired them
* in his simulation code (that is, he calls them wherever he wants to
* trigger a trace event), he needs to hook these trace sources into the
* global tracing namespace. The first step to do this is to define a method
* which returns a pointer to a ns3::TraceResolver object and which takes
* as argument a reference to a const ns3::TraceContext. The name of this method
* depends on how you will hook into the global tracing namespace. Before
* we get there, you need to implement this method. To do this, you could
* attempt to do everything by hand: define a subclass of the
* ns3::TraceResolver base class and implement its DoConnect, DoDisconnect
* and DoLookup methods. Because doing this can be a bit tedious, our
* tracing framework provides a number of helper template classes which
* should save you from having to implement your own in most cases:
* - ns3::CompositeTraceResolver: this subclass of ns3::TraceResolver
* can be used to aggregate together multiple trace sources and
* multiple other ns3::TraceResolver instances.
* - ns3::ArrayTraceResolver: this subclass of ns3::TraceResolver
* can be used to match any number of elements within an array
* where every element is identified by its index.
*
* Once you can instantiate your own ns3::TraceResolver object instance,
* you have to hook it up into the global namespace. There are two ways
* to do this:
* - you can hook your ns3::TraceResolver creation method as a new trace
* root by using the ns3::TraceRoot::Register method
* - you can hook your new ns3::TraceResolver creation method into
* the container of your model.
* For example, if you wrote a new l3 protocol, all you have to do
* to hook into your container L3Demux class is to implement
* the pure virtual method inherited from the L3Protocol class
* whose name is ns3::L3protocol::CreateTraceResolver.
*
* If you really want to have fun and implement your own ns3::TraceResolver
* subclass, you need to understand the basic Connection and Disconnection
* algorithm. The code of that algorithm is wholy contained in the
* ns3::TraceResolver::Connect and ns3::TraceResolver::Disconnect methods.
* The idea is that we recursively parse the input namespace string by removing
* the first namespace element. This element is 'resolved' is calling
* the ns3::TraceResolver::DoLookup method which returns a list of
* TraceResolver instances. Each of the returned TraceResolver instance is
* then given what is left of the namespace by calling ns3::TraceResolver::Connect
* until the last namespace element is processed. At this point, we invoke
* the ns3::TraceResolver::DoConnect or ns3::TraceResolver::DoDisconnect
* methods to break the recursion. A good way to understand this algorithm
* is to trace its behavior. Let's say that you want to connect to
* '/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *'. It would generate
* the following call traces:
*
* \code
* TraceRoot::Connect (/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *);
* resolver = NodeList::CreateTraceResolver ();
* resolver->Connect (/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *);
* list = CompositeTraceResolver::DoLookup ('nodes');
* resolver->Connect (/ * /ipv4/interfaces/ * /netdevice/queue/ *);
* list = ArrayTraceResolver::DoLookup ('*');
* resolver->Connect ('/ipv4/interfaces/ * /netdevice/queue/ *');
* list = CompositeTraceResolver::DoLookup ('ipv4');
* resolver->Connect ('/interfaces/ * /netdevice/queue/ *');
* list = CompositeTraceResolver::DoLookup ('interfaces');
* resolver->Connect ('/ * /netdevice/queue/ *');
* list = ArrayTraceResolver::DoLookup ('*');
* resolver->Connect ('/netdevice/queue/ *');
* list = CompositeTraceResolver::DoLookup ('netdevice');
* resolver->Connect ('/queue/ *');
* list = CompositeTraceResolver::DoLookup ('queue');
* resolver->Connect ('/ *');
* list = CompositeTraceResolver::DoLookup ('*');
* resolver->DoConnect ();
* \endcode
*
* This namespace resolution algorithm makes sure that each subpart of the
* namespace is resolved separately by each component. It allows you to
* never have to know the entire namespace structure to resolve a namespace
* string. All namespace knowledge is local which makes it very easy to plug
* in new components and have them extend the global tracing namespace.
*
* What is central to this namespace parsing and resolution algorithm is the
* construction of an ns3::TraceContext for each trace source during the
* connection process. The root trace context is intialized to be empty and
* TraceResolver::DoLookup method is responsible for incrementally constructing
* the TraceContext assigned to each terminal TraceSource object.
*/
namespace ns3 {
class CompositeTraceResolver;
class TraceResolver;
class TraceContext;
class CallbackBase;
/**
* \brief The main class used to access tracing functionality for
* a user.
*
* \ingroup tracing
*/
class TraceRoot
{
public:
static void Connect (std::string path, CallbackBase const &cb);
static void Disconnect (std::string path, CallbackBase const &cb);
static void Register (std::string name,
Callback<TraceResolver *,TraceContext const &> createResolver);
private:
static CompositeTraceResolver *GetComposite (void);
enum TraceType {
NOTHING,
};
};
}// namespace ns3
#endif /* TRACE_ROOT_H */

View File

@ -19,35 +19,39 @@
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef UI_VARIABLE_TRACER_H
#define UI_VARIABLE_TRACER_H
#ifndef UV_TRACE_SOURCE_H
#define UV_TRACE_SOURCE_H
#include "ns3/callback.h"
#include "callback-trace-source.h"
#include <stdint.h>
namespace ns3 {
class UiVariableTracerBase {
class UVTraceSourceBase {
public:
typedef Callback<void, uint64_t, uint64_t> ChangeNotifyCallback;
typedef CallbackTraceSource<uint64_t, uint64_t> ChangeNotifyCallback;
UiVariableTracerBase ()
UVTraceSourceBase ()
: m_callback () {}
/* We don't want to copy the base callback. Only setCallback on
* a specific instance will do something to it. */
UiVariableTracerBase (UiVariableTracerBase const &o)
UVTraceSourceBase (UVTraceSourceBase const &o)
: m_callback () {}
UiVariableTracerBase &operator = (UiVariableTracerBase const &o) {
UVTraceSourceBase &operator = (UVTraceSourceBase const &o) {
return *this;
}
~UiVariableTracerBase () {}
~UVTraceSourceBase () {}
void SetCallback(ChangeNotifyCallback callback) {
m_callback = callback;
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
m_callback.AddCallback (callback, context);
}
void RemoveCallback (CallbackBase const & callback) {
m_callback.RemoveCallback (callback);
}
protected:
void Notify (uint64_t oldVal, uint64_t newVal) {
if (oldVal != newVal && !m_callback.IsNull ())
if (oldVal != newVal)
{
m_callback (oldVal, newVal);
}
@ -57,11 +61,12 @@ private:
};
template <typename T>
class SiVariableTracer;
class SVTraceSource;
/**
* \brief trace variables of type "unsigned integer"
* \ingroup tracing
*
* This template class implements a POD type: it
* behaves like any other variable of type "unsigned integer"
@ -70,12 +75,12 @@ class SiVariableTracer;
*
* To instantiate a 32-bit unsigned variable (to store
* a TCP counter for example), you would create a variable of type
* ns3::UiVariableTracer<uint32_t> :
* ns3::UVTraceSource<uint32_t> :
\code
#include <stdint.h>
#include "ns3/ui-traced-variable.tcc"
#include "ns3/uv-trace-source.h"
ns3::UiVariableTracer<uint32_t> var;
ns3::UVTraceSource<uint32_t> var;
\endcode
* and you would use it like any other variable of type uint32_t:
\code
@ -84,44 +89,44 @@ class SiVariableTracer;
\endcode
*/
template <typename T>
class UiVariableTracer : public UiVariableTracerBase {
class UVTraceSource : public UVTraceSourceBase {
public:
UiVariableTracer ()
UVTraceSource ()
: m_var ()
{}
UiVariableTracer (T const &var)
UVTraceSource (T const &var)
: m_var (var)
{}
UiVariableTracer &operator = (UiVariableTracer const &o) {
UVTraceSource &operator = (UVTraceSource const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
UiVariableTracer &operator = (UiVariableTracer<TT> const &o) {
UVTraceSource &operator = (UVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
template <typename TT>
UiVariableTracer &operator = (SiVariableTracer<TT> const &o) {
UVTraceSource &operator = (SVTraceSource<TT> const &o) {
Assign (o.Get ());
return *this;
}
UiVariableTracer &operator++ () {
UVTraceSource &operator++ () {
Assign (Get () + 1);
return *this;
}
UiVariableTracer &operator-- () {
UVTraceSource &operator-- () {
Assign (Get () - 1);
return *this;
}
UiVariableTracer operator++ (int) {
UiVariableTracer old (*this);
UVTraceSource operator++ (int) {
UVTraceSource old (*this);
++*this;
return old;
}
UiVariableTracer operator-- (int) {
UiVariableTracer old (*this);
UVTraceSource operator-- (int) {
UVTraceSource old (*this);
--*this;
return old;
}
@ -143,98 +148,98 @@ private:
};
template <typename T>
UiVariableTracer<T> &operator += (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator += (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () + rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator -= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator -= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () - rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator *= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator *= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () * rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator /= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator /= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () / rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator <<= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator <<= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () << rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator >>= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator >>= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () >> rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator &= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator &= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () & rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator |= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator |= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () | rhs.Get ());
return lhs;
}
template <typename T>
UiVariableTracer<T> &operator ^= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
UVTraceSource<T> &operator ^= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
lhs.Assign (lhs.Get () ^ rhs.Get ());
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator += (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator += (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () + rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator -= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator -= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () - rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator *= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator *= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () * rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator /= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator /= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () / rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator <<= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator <<= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () << rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator >>= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator >>= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () >> rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator &= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator &= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () & rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator |= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator |= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () | rhs);
return lhs;
}
template <typename T, typename U>
UiVariableTracer<T> &operator ^= (UiVariableTracer<T> &lhs, U const &rhs) {
UVTraceSource<T> &operator ^= (UVTraceSource<T> &lhs, U const &rhs) {
lhs.Assign (lhs.Get () ^ rhs);
return lhs;
}
}; // namespace ns3
#endif /* UI_VARIABLE_TRACER_H */
#endif /* UV_TRACE_SOURCE_H */

View File

@ -19,8 +19,9 @@
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "ui-variable-tracer.h"
#include "si-variable-tracer.h"
#include "uv-trace-source.h"
#include "sv-trace-source.h"
#include "trace-context.h"
#include "ns3/test.h"
#include "ns3/callback.h"
@ -29,7 +30,7 @@ namespace ns3 {
class Foo {
public:
void Notify (uint64_t oldVal, uint64_t newVal) {}
void Notify (TraceContext const &contex, uint64_t oldVal, uint64_t newVal) {}
};
class VariableTracerTest: public Test {
@ -42,11 +43,11 @@ public:
void
VariableTracerTest::RunUnsignedTests (void)
{
UiVariableTracer<uint32_t> var, ovar, tmp;
UVTraceSource<uint32_t> var, ovar, tmp;
uint32_t utmp;
Foo *foo = new Foo ();
var.SetCallback (MakeCallback (&Foo::Notify, foo));
var.AddCallback (MakeCallback (&Foo::Notify, foo), TraceContext ());
var = 10;
ovar = var;
@ -227,10 +228,10 @@ VariableTracerTest::RunSignedUnsignedTests (void)
uitmp = utmp;
utmp = uitmp;
UiVariableTracer<unsigned short> uvar = 10;
UiVariableTracer<unsigned int> uivar = 5;
SiVariableTracer<short> svar = 5;
SiVariableTracer<int> sivar = 5;
UVTraceSource<unsigned short> uvar = 10;
UVTraceSource<unsigned int> uivar = 5;
SVTraceSource<short> svar = 5;
SVTraceSource<int> sivar = 5;
uvar = svar;
svar = uvar;
uvar += svar;

View File

@ -47,6 +47,16 @@ int Test7 (int a)
return a;
}
void *Test9 (bool *a)
{
return a;
}
void *Test10 (bool *a, int const & b)
{
return a;
}
class CallbackTest : public ns3::Test {
private:
bool m_test1;
@ -147,9 +157,9 @@ CallbackTest::RunTests (void)
b0 = B (this, &CallbackTest::Test2);
C c0 = C (this, &CallbackTest::Test3);
D d0 = D (this, &CallbackTest::Test4);
E e0 = E (&Test5);
F f0 = F (&Test6);
G g0 = G (&Test7);
E e0 = E (&Test5, true, true);
F f0 = F (&Test6, true, true);
G g0 = G (&Test7, true, true);
a0 ();
b0 ();
@ -190,6 +200,13 @@ CallbackTest::RunTests (void)
{
ok = false;
}
MakeBoundCallback (&Test7, 0);
bool v;
MakeBoundCallback (&Test9, &v);
MakeBoundCallback (&Test10, &v);
return ok;
}

View File

@ -60,6 +60,7 @@ class empty {};
class CallbackImplBase {
public:
virtual ~CallbackImplBase () {}
virtual bool IsEqual (CallbackImplBase const *other) const = 0;
};
// declare the CallbackImpl class
@ -134,6 +135,19 @@ public:
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return m_functor (a1,a2,a3,a4,a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *otherDerived =
dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *> (other);
if (otherDerived == 0)
{
return false;
}
else if (otherDerived->m_functor != m_functor)
{
return false;
}
return true;
}
private:
T m_functor;
};
@ -163,6 +177,20 @@ public:
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return ((*m_objPtr).*m_memPtr) (a1,a2,a3,a4,a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *otherDerived =
dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *> (other);
if (otherDerived == 0)
{
return false;
}
else if (otherDerived->m_objPtr != m_objPtr ||
otherDerived->m_memPtr != m_memPtr)
{
return false;
}
return true;
}
private:
OBJ_PTR const m_objPtr;
MEM_PTR m_memPtr;
@ -202,14 +230,17 @@ public:
* as well as the function templates \ref MakeCallback :
* \include samples/main-callback.cc
*/
template<typename R,
typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty,
typename T5 = empty>
class Callback : public CallbackBase {
public:
// There are two dummy args below to ensure that this constructor is
// always properly disambiguited by the c++ compiler
template <typename FUNCTOR>
Callback (FUNCTOR const &functor)
Callback (FUNCTOR const &functor, bool, bool)
: m_impl (new FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> (functor))
{}
@ -227,25 +258,29 @@ public:
}
Callback () : m_impl () {}
R operator() (void) {
R operator() (void) const {
return (*(m_impl.Get ())) ();
}
R operator() (T1 a1) {
R operator() (T1 a1) const {
return (*(m_impl.Get ())) (a1);
}
R operator() (T1 a1, T2 a2) {
R operator() (T1 a1, T2 a2) const {
return (*(m_impl).Get ()) (a1,a2);
}
R operator() (T1 a1, T2 a2, T3 a3) {
R operator() (T1 a1, T2 a2, T3 a3) const {
return (*(m_impl).Get ()) (a1,a2,a3);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4) {
R operator() (T1 a1, T2 a2, T3 a3, T4 a4) const {
return (*(m_impl).Get ()) (a1,a2,a3,a4);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) {
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const {
return (*(m_impl).Get ()) (a1,a2,a3,a4,a5);
}
bool IsEqual (CallbackBase const &other) {
return PeekImpl ()->IsEqual (other.PeekImpl ());
}
bool CheckType (CallbackBase const& other) {
CallbackImplBase *otherBase = other.PeekImpl ();
if (dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5> *> (otherBase) != 0)
@ -351,7 +386,7 @@ Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5), OBJ
*/
template <typename R>
Callback<R> MakeCallback (R (*fnPtr) ()) {
return Callback<R> (fnPtr);
return Callback<R> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
@ -362,7 +397,7 @@ Callback<R> MakeCallback (R (*fnPtr) ()) {
*/
template <typename R, typename T1>
Callback<R,T1> MakeCallback (R (*fnPtr) (T1)) {
return Callback<R,T1> (fnPtr);
return Callback<R,T1> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
@ -373,7 +408,7 @@ Callback<R,T1> MakeCallback (R (*fnPtr) (T1)) {
*/
template <typename R, typename T1, typename T2>
Callback<R,T1,T2> MakeCallback (R (*fnPtr) (T1,T2)) {
return Callback<R,T1,T2> (fnPtr);
return Callback<R,T1,T2> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
@ -384,7 +419,7 @@ Callback<R,T1,T2> MakeCallback (R (*fnPtr) (T1,T2)) {
*/
template <typename R, typename T1, typename T2,typename T3>
Callback<R,T1,T2,T3> MakeCallback (R (*fnPtr) (T1,T2,T3)) {
return Callback<R,T1,T2,T3> (fnPtr);
return Callback<R,T1,T2,T3> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
@ -395,7 +430,7 @@ Callback<R,T1,T2,T3> MakeCallback (R (*fnPtr) (T1,T2,T3)) {
*/
template <typename R, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> MakeCallback (R (*fnPtr) (T1,T2,T3,T4)) {
return Callback<R,T1,T2,T3,T4> (fnPtr);
return Callback<R,T1,T2,T3,T4> (fnPtr, true, true);
}
/**
* \ingroup MakeCallback
@ -406,7 +441,7 @@ Callback<R,T1,T2,T3,T4> MakeCallback (R (*fnPtr) (T1,T2,T3,T4)) {
*/
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) {
return Callback<R,T1,T2,T3,T4,T5> (fnPtr);
return Callback<R,T1,T2,T3,T4,T5> (fnPtr, true, true);
}
@ -503,11 +538,34 @@ public:
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
return m_functor (m_a,a1,a2,a3,a4,a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *otherDerived =
dynamic_cast<BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *> (other);
if (otherDerived == 0)
{
return false;
}
else if (otherDerived->m_functor != m_functor ||
otherDerived->m_a != m_a)
{
return false;
}
return true;
}
private:
T m_functor;
TX m_a;
};
template <typename R, typename TX>
Callback<R> MakeBoundCallback (R (*fnPtr) (TX), TX a) {
ReferenceList<CallbackImpl<R,empty,empty,empty,empty,empty>*> impl =
ReferenceList<CallbackImpl<R,empty,empty,empty,empty,empty>*> (
new BoundFunctorCallbackImpl<R (*) (TX),R,TX,empty,empty,empty,empty,empty> (fnPtr, a)
);
return Callback<R> (impl);
}
template <typename R, typename TX, typename T1>
Callback<R,T1> MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) {
ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> impl =

View File

@ -22,10 +22,9 @@
#define FATAL_ERROR_H
#include "assert.h"
#include <iostream>
/**
* \defgroup error
* \defgroup error Error
* \brief fatal error handling
*
* \param msg message to output when this macro is hit.

View File

@ -22,6 +22,7 @@
// Implementation of a point-to-point network device
// George F. Riley, Georgia Tech, Spring 2007
#include "ns3/empty-trace-resolver.h"
#include "p2p-net-device.h"
#include "p2p-channel.h"
@ -60,6 +61,12 @@ P2PNetDevice::SendTo (Packet& p, const MacAddress&)
return true;
}
TraceResolver *
P2PNetDevice::DoCreateTraceResolver (TraceContext const &context)
{
return new EmptyTraceResolver (context);
}
void
P2PNetDevice::Receive(Packet p)
{

View File

@ -42,6 +42,8 @@ public:
void TxComplete (void);
private:
virtual bool SendTo (Packet& p, const MacAddress& dest);
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
double m_rate;
P2PChannel *m_channel;
};

View File

@ -21,6 +21,7 @@
#include "serial-channel.h"
#include "serial-net-device.h"
#include "serial-phy.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/debug.h"
@ -32,7 +33,8 @@ namespace ns3 {
//
// By default, you get a channel with the name "Serial Channel" that has an
// "infitely" fast transmission speed and zero delay.
//
// XXX: this does not work because m_bps = 0 results in infinitely slow transmission
// speed.
SerialChannel::SerialChannel()
:
Channel ("Serial Channel"),
@ -58,13 +60,13 @@ SerialChannel::SerialChannel(
}
void
SerialChannel::Attach(SerialNetDevice *device)
SerialChannel::Attach(SerialPhy *phy)
{
NS_DEBUG("SerialChannel::Attach (" << device << ")");
NS_DEBUG("SerialChannel::Attach (" << phy << ")");
NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
NS_ASSERT(device);
NS_ASSERT(phy);
m_link[m_nDevices].m_src = device;
m_link[m_nDevices].m_src = phy;
++m_nDevices;
//
// If we have both devices connected to the channel, then finish introducing
@ -79,8 +81,8 @@ SerialChannel::Attach(SerialNetDevice *device)
}
}
void
SerialChannel::TransmitCompleteEvent(Packet &p, SerialNetDevice *src)
void
SerialChannel::TransmitCompleteEvent(Packet p, SerialPhy *src)
{
NS_DEBUG("SerialChannel::TransmitCompleteEvent (" << &p << ", " <<
src << ")");
@ -97,8 +99,8 @@ SerialChannel::TransmitCompleteEvent(Packet &p, SerialNetDevice *src)
m_link[wire].m_dst->Receive (p);
}
bool
SerialChannel::Propagate(Packet& p, SerialNetDevice* src)
bool
SerialChannel::Propagate(Packet& p, SerialPhy* src)
{
NS_DEBUG("SerialChannel::DoPropagate (" << &p << ", " << src << ")");
@ -119,19 +121,27 @@ SerialChannel::Propagate(Packet& p, SerialNetDevice* src)
// I believe Raj has a method in the DataRate class to do this. Should use
// it when it is available.
//
Time tEvent = Simulator::Now () +
Seconds (static_cast<double> (p.GetSize() * 8) /
static_cast<double> (m_bps)) + m_delay;
Time tEvent = Seconds (static_cast<double> (p.GetSize() * 8) /
static_cast<double> (m_bps)) + m_delay;
NS_DEBUG("SerialChannel::DoSend (): Schedule Receive at " << tEvent);
NS_DEBUG("SerialChannel::DoSend (): Schedule Receive delay " << tEvent);
#if 0
Packet packet = p;
Simulator::Schedule (tEvent, &SerialChannel::TransmitCompleteEvent, this,
p, src);
#else
TransmitCompleteEvent (p, src);
#endif
p, src);
return true;
}
uint32_t
SerialChannel::GetNDevices (void) const
{
return m_nDevices;
}
NetDevice *
SerialChannel::GetDevice (uint32_t i) const
{
return m_link[i].m_src->GetDevice ();
}
} // namespace ns3

View File

@ -20,8 +20,7 @@
#define SERIAL_CHANNEL_H
#include <list>
#include "channel.h"
#include "serial-phy.h"
#include "ns3/channel.h"
#include "ns3/packet.h"
#include "ns3/nstime.h"
@ -29,6 +28,8 @@ namespace ns3 {
// temporary until Raj's code makes it into the dev tree
typedef uint64_t DataRate;
class SerialPhy;
class NetDevice;
/**
* \brief Simple Serial Channel.
@ -60,11 +61,15 @@ public:
SerialChannel ();
SerialChannel (std::string name, DataRate bps, Time delay);
void Attach (SerialNetDevice* nd);
bool Propagate (Packet& p, SerialNetDevice *src);
void Attach (SerialPhy* phy);
bool Propagate (Packet& p, SerialPhy *src);
protected:
void TransmitCompleteEvent (Packet &p, SerialNetDevice *src);
virtual uint32_t GetNDevices (void) const;
virtual NetDevice *GetDevice (uint32_t i) const;
private:
void TransmitCompleteEvent (Packet p, SerialPhy *src);
std::string m_name;
DataRate m_bps;
@ -83,9 +88,9 @@ protected:
{
public:
Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
WireState m_state;
SerialNetDevice *m_src;
SerialNetDevice *m_dst;
WireState m_state;
SerialPhy *m_src;
SerialPhy *m_dst;
};
Link m_link[N_DEVICES];

View File

@ -23,6 +23,7 @@
#include <cassert>
#include "ns3/debug.h"
#include "ns3/queue.h"
#include "ns3/composite-trace-resolver.h"
#include "serial-net-device.h"
#include "serial-channel.h"
#include "serial-phy.h"
@ -51,10 +52,11 @@ SerialNetDevice::SerialNetDevice(Node* node, const MacAddress& addr) :
SerialNetDevice::~SerialNetDevice()
{
NS_DEBUG ("SerialNetDevice::~SerialNetDevice ()");
delete m_phy;
}
bool
bool
SerialNetDevice::SendTo (Packet& p, const MacAddress& dest)
{
NS_DEBUG ("SerialNetDevice::SendTo (" << &p << ", " << &dest << ")");
@ -74,12 +76,23 @@ SerialNetDevice::SendTo (Packet& p, const MacAddress& dest)
return false;
}
bool
TraceResolver *
SerialNetDevice::DoCreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
resolver->Add ("queue",
MakeCallback (&Queue::CreateTraceResolver, m_queue),
SerialNetDevice::QUEUE);
return resolver;
}
bool
SerialNetDevice::Attach (SerialChannel* ch)
{
NS_DEBUG ("SerialNetDevice::Attach (" << &ch << ")");
m_channel = ch;
m_phy->Attach (m_channel);
/*
* For now, this device is up whenever a channel is attached to it.
* In fact, it should become up only when the second device
@ -106,8 +119,7 @@ SerialNetDevice::Receive (Packet& p)
// ignore return value for now.
NS_DEBUG ("SerialNetDevice::Receive (" << &p << ")");
// Dispatch this to SerialPhy::Receive
m_phy->Receive (p);
ForwardUp (p);
}
void
@ -125,7 +137,7 @@ SerialNetDevice::NotifyDataAvailable(void)
// send packet to address tag.address
#endif
NS_DEBUG ("SerialNetDevice::NotifyDataAvailable (): Dequeued");
m_channel->Propagate(p, this);
m_phy->Send(p);
}
}

View File

@ -35,8 +35,10 @@ class SerialPhy;
class Queue;
class SerialNetDevice : public NetDevice {
friend class SerialPhy;
public:
enum TraceType {
QUEUE,
};
SerialNetDevice(Node* node, const MacAddress& addr);
virtual ~SerialNetDevice();
@ -48,7 +50,7 @@ private:
public:
bool Attach(SerialChannel* ch);
void AddQueue(Queue *);
// called by ChannelSerial
// called by SerialPhy
void Receive (Packet& p);
protected:
@ -58,6 +60,7 @@ protected:
private:
virtual void NotifyDataAvailable (void);
virtual bool SendTo (Packet& p, const MacAddress& dest);
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
SerialPhy* m_phy;
SerialChannel* m_channel;

View File

@ -40,30 +40,31 @@ SerialPhy::~SerialPhy()
NS_DEBUG ("SerialPhy::~SerialPhy ()");
}
void
SerialPhy::NotifyDataAvailable(void)
void
SerialPhy::Send (Packet &p)
{
NS_DEBUG ("SerialPhy::NotifyDataAvailable ()");
Packet p;
bool found = m_netdevice->GetQueue ()->Dequeue (p);
if (found)
{
#ifdef NOTYET
struct NetDevicePacketDestAddress tag;
p.PeekTag (tag);
// send packet to address tag.address
#endif
NS_DEBUG ("SerialPhy::NotifyDataAvailable (): Dequeued");
m_netdevice->GetChannel()->Propagate(p, m_netdevice);
}
m_channel->Propagate (p, this);
}
void
SerialPhy::Attach (SerialChannel *channel)
{
m_channel = channel;
m_channel->Attach (this);
}
SerialNetDevice *
SerialPhy::GetDevice (void)
{
return m_netdevice;
}
void
SerialPhy::Receive (Packet& p)
{
NS_DEBUG ("SerialPhy::Receive (" << &p << ")");
m_netdevice->ForwardUp (p);
m_netdevice->Receive (p);
}
} // namespace ns3

View File

@ -21,22 +21,27 @@
#ifndef SERIAL_PHY_H
#define SERIAL_PHY_H
#include <string.h>
#include "ns3/internet-node.h"
#include "ns3/packet.h"
#include "serial-net-device.h"
namespace ns3 {
class SerialNetDevice;
class SerialChannel;
class Node;
class Packet;
class SerialPhy {
public:
SerialPhy(Node* node, SerialNetDevice* netdevice);
virtual ~SerialPhy();
virtual void NotifyDataAvailable (void);
void Send (Packet &p);
void Receive (Packet& p);
void Attach (SerialChannel *channel);
SerialNetDevice *GetDevice (void);
private:
Node* m_node;
SerialChannel *m_channel;
SerialNetDevice* m_netdevice;
};

View File

@ -21,6 +21,7 @@
*/
#include "ns3/packet.h"
#include "ns3/composite-trace-resolver.h"
#include "arp-ipv4-interface.h"
#include "arp.h"
@ -37,6 +38,20 @@ ArpIpv4Interface::ArpIpv4Interface (Node *node, NetDevice *device)
ArpIpv4Interface::~ArpIpv4Interface ()
{}
TraceResolver *
ArpIpv4Interface::DoCreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
if (GetDevice () != 0)
{
resolver->Add ("netdevice",
MakeCallback (&NetDevice::CreateTraceResolver, GetDevice ()),
ArpIpv4Interface::NETDEVICE);
}
return resolver;
}
void
ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest)
{

View File

@ -31,11 +31,16 @@ class Node;
class ArpIpv4Interface : public Ipv4Interface
{
public:
enum TraceType {
NETDEVICE,
ARP,
};
ArpIpv4Interface (Node *node, NetDevice *device);
virtual ~ArpIpv4Interface ();
private:
virtual void SendTo (Packet p, Ipv4Address dest);
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
Node *m_node;
};

View File

@ -20,6 +20,7 @@
*/
#include "ns3/packet.h"
#include "ns3/debug.h"
#include "ns3/empty-trace-resolver.h"
#include "arp.h"
#include "arp-header.h"
#include "arp-cache.h"
@ -53,6 +54,12 @@ Arp::Copy (Node *node) const
return new Arp (node);
}
TraceResolver *
Arp::CreateTraceResolver (TraceContext const &context)
{
return new EmptyTraceResolver (context);
}
ArpCache *
Arp::FindCache (NetDevice *device)
{

View File

@ -32,6 +32,8 @@ class ArpCache;
class NetDevice;
class Node;
class Packet;
class TraceResolver;
class TraceContext;
class Arp : public L3Protocol
{
@ -42,6 +44,8 @@ public:
~Arp ();
virtual Arp *Copy (Node *node) const;
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
virtual void Receive(Packet& p, NetDevice &device);
bool Lookup (Packet &p, Ipv4Address destination,
NetDevice *device,

View File

@ -33,8 +33,8 @@ Channel::Channel ()
NS_DEBUG("Channel::Channel ()");
}
Channel::Channel (std::string name)
: m_name(name)
Channel::Channel (std::string name)
: m_name(name)
{
NS_DEBUG("Channel::Channel (" << name << ")");
}

View File

@ -19,16 +19,16 @@
*
* Wed Feb 14 16:05:46 PST 2007 craigdo: Created
*/
#include <list>
#include "ns3/packet.h"
#include "layer-connector.h"
#ifndef CHANNEL_H
#define CHANNEL_H
#include <string>
#include <stdint.h>
namespace ns3 {
class NetDevice;
/**
* \brief Abstract Channel Base Class.
*
@ -42,8 +42,11 @@ public:
Channel (std::string name);
virtual ~Channel ();
virtual void SetName(std::string);
virtual std::string GetName(void);
void SetName(std::string);
std::string GetName(void);
virtual uint32_t GetNDevices (void) const = 0;
virtual NetDevice *GetDevice (uint32_t i) const = 0;
protected:
std::string m_name;

View File

@ -25,34 +25,19 @@ NS_DEBUG_COMPONENT_DEFINE ("DropTailQueue");
namespace ns3 {
DropTailQueue::DropTailQueue () :
Queue (""),
Queue (),
m_packets (),
m_maxPackets(DTQ_NPACKETS_MAX_DEFAULT)
{
NS_DEBUG("DropTailQueue::DropTailQueue ()");
}
DropTailQueue::DropTailQueue (std::string const&name)
: Queue (name),
m_packets(),
m_maxPackets(DTQ_NPACKETS_MAX_DEFAULT)
{
NS_DEBUG("DropTailQueue::DropTailQueue");
}
DropTailQueue::~DropTailQueue ()
{
NS_DEBUG("DropTailQueue::~DropTailQueue ()");
}
void
DropTailQueue::RegisterTraces (TraceContainer &traceContainer)
{
Queue::QueueRegisterTraces (traceContainer);
}
void
DropTailQueue::SetMaxPackets (uint32_t npackets)
{
NS_DEBUG("DropTailQueue::SetMaxPackets (" << npackets << ")");
@ -60,7 +45,7 @@ DropTailQueue::SetMaxPackets (uint32_t npackets)
m_maxPackets = npackets;
}
uint32_t
uint32_t
DropTailQueue::GetMaxPackets (void)
{
NS_DEBUG("DropTailQueue::GetMaxPackets () <= " << m_maxPackets);
@ -68,12 +53,12 @@ DropTailQueue::GetMaxPackets (void)
return m_maxPackets;
}
bool
bool
DropTailQueue::DoEnqueue (const Packet& p)
{
NS_DEBUG("DropTailQueue::DoEnqueue (" << &p << ")");
if (GetNPackets () >= m_maxPackets)
if (m_packets.size () >= m_maxPackets)
{
NS_DEBUG("DropTailQueue::DoEnqueue (): Queue full -- droppping pkt");
Drop (p);
@ -84,7 +69,7 @@ DropTailQueue::DoEnqueue (const Packet& p)
return true;
}
bool
bool
DropTailQueue::DoDequeue (Packet& p)
{
NS_DEBUG("DropTailQueue::DoDequeue (" << &p << ")");

View File

@ -33,9 +33,6 @@ const int DTQ_NPACKETS_MAX_DEFAULT = 100;
class DropTailQueue : public Queue {
public:
DropTailQueue ();
DropTailQueue (std::string const &name);
void RegisterTraces (TraceContainer &traceContainer);
virtual ~DropTailQueue();

View File

@ -21,6 +21,8 @@
// Implementation of the InternetNode class for ns3.
// George F. Riley, Georgia Tech, Fall 2006
#include "ns3/composite-trace-resolver.h"
#include "net-device-list.h"
#include "l3-demux.h"
#include "ipv4-l4-demux.h"
@ -96,6 +98,22 @@ InternetNode::Copy() const
return copy;
}
TraceResolver *
InternetNode::CreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
resolver->Add ("ipv4",
MakeCallback (&Ipv4::CreateTraceResolver, GetIpv4 ()),
InternetNode::IPV4);
resolver->Add ("arp",
MakeCallback (&Arp::CreateTraceResolver, GetArp ()),
InternetNode::ARP);
resolver->Add ("udp",
MakeCallback (&Udp::CreateTraceResolver, GetUdp ()),
InternetNode::UDP);
return resolver;
}
NetDeviceList*
InternetNode::GetNetDeviceList() const

View File

@ -35,11 +35,17 @@ namespace ns3 {
class InternetNode : public Node
{
public:
enum TraceType {
IPV4,
UDP,
ARP,
};
InternetNode();
InternetNode(const InternetNode&);
InternetNode const &operator = (InternetNode const &o);
virtual ~InternetNode ();
virtual InternetNode* Copy() const;
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
// Capability access
virtual NetDeviceList* GetNetDeviceList() const;
virtual L3Demux* GetL3Demux() const;

View File

@ -45,6 +45,12 @@ Ipv4Interface::GetDevice (void) const
return m_netdevice;
}
TraceResolver *
Ipv4Interface::CreateTraceResolver (TraceContext const &context)
{
return DoCreateTraceResolver (context);
}
void
Ipv4Interface::SetAddress (Ipv4Address a)
{

View File

@ -30,6 +30,8 @@ namespace ns3 {
class NetDevice;
class Packet;
class TraceResolver;
class TraceContext;
/**
* \brief The IPv4 representation of a network interface
@ -62,6 +64,7 @@ public:
Ipv4Interface (NetDevice *nd);
virtual ~Ipv4Interface();
TraceResolver *CreateTraceResolver (TraceContext const &context);
NetDevice *GetDevice (void) const;
void SetAddress (Ipv4Address a);
@ -96,6 +99,7 @@ public:
private:
virtual void SendTo (Packet p, Ipv4Address dest) = 0;
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
NetDevice* m_netdevice;
bool m_ifup;
Ipv4Address m_address;

View File

@ -22,6 +22,8 @@
// Define the layer 4 demultiplexer object for ns3.
// George F. Riley, Georgia Tech, Fall 2006
#include <sstream>
#include "ns3/composite-trace-resolver.h"
#include "ipv4-l4-demux.h"
#include "ipv4-l4-protocol.h"
@ -48,6 +50,23 @@ Ipv4L4Demux::Copy(Node *node) const
}
return copy;
}
TraceResolver *
Ipv4L4Demux::CreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
{
Ipv4L4Protocol *protocol = *i;
std::string protValue;
std::ostringstream oss (protValue);
oss << (*i)->GetProtocolNumber ();
Ipv4L4ProtocolTraceType protocolNumber = (*i)->GetProtocolNumber ();
resolver->Add (protValue,
MakeCallback (&Ipv4L4Protocol::CreateTraceResolver, protocol),
protocolNumber);
}
return resolver;
}
Ipv4L4Protocol*
Ipv4L4Demux::Insert(const Ipv4L4Protocol&protocol)
{

View File

@ -32,12 +32,16 @@ namespace ns3 {
class Ipv4L4Protocol;
class Node;
class TraceResolver;
class TraceContext;
class Ipv4L4Demux {
public:
typedef int Ipv4L4ProtocolTraceType;
Ipv4L4Demux (Node *node);
virtual ~Ipv4L4Demux();
Ipv4L4Demux* Copy(Node *node) const;
TraceResolver *CreateTraceResolver (TraceContext const &context);
Ipv4L4Protocol* Insert(const Ipv4L4Protocol&);
Ipv4L4Protocol* Lookup(int protocolNumber);
void Erase(Ipv4L4Protocol*);

View File

@ -31,6 +31,8 @@ namespace ns3 {
class Node;
class Packet;
class Ipv4Address;
class TraceResolver;
class TraceContext;
class Ipv4L4Protocol {
public:
@ -41,6 +43,7 @@ public:
int GetVersion() const;
virtual Ipv4L4Protocol* Copy(Node *node) const = 0;
virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
/**
* Called from lower-level layers to send the packet up
* in the stack.

View File

@ -19,6 +19,7 @@
* Authors:
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
*/
#include "ns3/empty-trace-resolver.h"
#include "ipv4-loopback-interface.h"
#include "net-device.h"
#include "node.h"
@ -33,6 +34,7 @@ public:
Node *PeekNode (void) const;
private:
virtual bool SendTo (Packet& p, const MacAddress& dest);
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
};
Ipv4DummyNetDevice::Ipv4DummyNetDevice (Node *node)
@ -50,6 +52,11 @@ Ipv4DummyNetDevice::SendTo (Packet& p, const MacAddress& dest)
{
return false;
}
TraceResolver *
Ipv4DummyNetDevice::DoCreateTraceResolver (TraceContext const &context)
{
return new EmptyTraceResolver (context);
}
Ipv4LoopbackInterface::Ipv4LoopbackInterface (Node *node)
@ -68,6 +75,12 @@ Ipv4LoopbackInterface::GetNode (void) const
return m_node;
}
TraceResolver *
Ipv4LoopbackInterface::DoCreateTraceResolver (TraceContext const &context)
{
return new EmptyTraceResolver (context);
}
void
Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest)
{

View File

@ -36,6 +36,7 @@ class Ipv4LoopbackInterface : public Ipv4Interface
private:
virtual void SendTo (Packet p, Ipv4Address dest);
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
Node *GetNode (void) const;
Node *m_node;

View File

@ -21,6 +21,9 @@
#include "ns3/packet.h"
#include "ns3/debug.h"
#include "ns3/composite-trace-resolver.h"
#include "ns3/array-trace-resolver.h"
#include "ns3/callback.h"
#include "ipv4.h"
#include "ipv4-l4-protocol.h"
@ -68,6 +71,30 @@ Ipv4::~Ipv4 ()
delete m_defaultRoute;
}
TraceResolver *
Ipv4::CreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
resolver->Add ("tx", m_txTrace, Ipv4::TX);
resolver->Add ("rx", m_rxTrace, Ipv4::RX);
resolver->Add ("drop", m_dropTrace, Ipv4::DROP);
resolver->Add ("interfaces",
MakeCallback (&Ipv4::InterfacesCreateTraceResolver, this),
Ipv4::INTERFACES);
return resolver;
}
TraceResolver *
Ipv4::InterfacesCreateTraceResolver (TraceContext const &context)
{
ArrayTraceResolver<Ipv4Interface> *resolver =
new ArrayTraceResolver<Ipv4Interface>
(context,
MakeCallback (&Ipv4::GetNInterfaces, this),
MakeCallback (&Ipv4::GetInterface, this));
return resolver;
}
void
Ipv4::SetDefaultTtl (uint8_t ttl)
{
@ -77,8 +104,8 @@ Ipv4::SetDefaultTtl (uint8_t ttl)
void
Ipv4::AddHostRouteTo (Ipv4Address dest,
Ipv4Address nextHop,
uint32_t interface)
Ipv4Address nextHop,
uint32_t interface)
{
Ipv4Route *route = new Ipv4Route ();
*route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
@ -281,7 +308,7 @@ Ipv4::GetInterface (uint32_t index)
return 0;
}
uint32_t
Ipv4::GetNInterfaces (void) const
Ipv4::GetNInterfaces (void)
{
return m_nInterfaces;
}
@ -309,7 +336,7 @@ Ipv4::Copy(Node *node) const
void
Ipv4::Receive(Packet& packet, NetDevice &device)
{
// XXX trace here.
m_rxTrace (packet);
Ipv4Header ipHeader;
packet.Peek (ipHeader);
packet.Remove (ipHeader);
@ -357,6 +384,7 @@ Ipv4::Send (Packet const &packet,
if (route == 0)
{
NS_DEBUG ("not for me -- forwarding but no route to host. drop.");
m_dropTrace (packet);
return;
}
@ -370,7 +398,7 @@ Ipv4::SendRealOut (Packet const &p, Ipv4Header const &ip, Ipv4Route const &route
packet.Add (ip);
Ipv4Interface *outInterface = GetInterface (route.GetInterface ());
NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ());
// XXX log trace here.
m_txTrace (packet);
if (route.IsGateway ())
{
outInterface->Send (packet, route.GetGateway ());
@ -425,6 +453,7 @@ Ipv4::Forwarding (Packet const &packet, Ipv4Header &ipHeader, NetDevice &device)
// Should send ttl expired here
// XXX
NS_DEBUG ("not for me -- ttl expired. drop.");
m_dropTrace (packet);
return true;
}
ipHeader.SetTtl (ipHeader.GetTtl () - 1);
@ -432,6 +461,7 @@ Ipv4::Forwarding (Packet const &packet, Ipv4Header &ipHeader, NetDevice &device)
if (route == 0)
{
NS_DEBUG ("not for me -- forwarding but no route to host. drop.");
m_dropTrace (packet);
return true;
}
NS_DEBUG ("not for me -- forwarding.");

View File

@ -24,6 +24,8 @@
#include <list>
#include <stdint.h>
#include "ns3/callback-trace-source.h"
#include "ns3/array-trace-resolver.h"
#include "ipv4-address.h"
#include "l3-protocol.h"
@ -36,6 +38,8 @@ class Ipv4Address;
class Ipv4Header;
class Ipv4Route;
class Node;
class TraceResolver;
class TraceContext;
/**
@ -46,9 +50,19 @@ class Ipv4 : public L3Protocol
public:
static const uint16_t PROT_NUMBER;
enum TraceType {
TX,
RX,
DROP,
INTERFACES,
};
typedef ArrayTraceResolver<Ipv4Interface>::Index InterfaceIndex;
Ipv4(Node *node);
virtual ~Ipv4 ();
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
void SetDefaultTtl (uint8_t ttl);
/* add route to host dest through host nextHop
@ -88,7 +102,7 @@ public:
uint32_t AddInterface (Ipv4Interface *interface);
Ipv4Interface * GetInterface (uint32_t i);
uint32_t GetNInterfaces (void) const;
uint32_t GetNInterfaces (void);
Ipv4Interface *FindInterfaceForDevice (NetDevice const*device);
@ -109,6 +123,7 @@ public:
void SendRealOut (Packet const &packet, Ipv4Header const &ip, Ipv4Route const &route);
bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, NetDevice &device);
void ForwardUp (Packet p, Ipv4Header const&ip);
TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context);
typedef std::list<Ipv4Interface*> Ipv4InterfaceList;
typedef std::list<Ipv4Route *> HostRoutes;
@ -126,6 +141,9 @@ public:
NetworkRoutes m_networkRoutes;
Ipv4Route *m_defaultRoute;
Node *m_node;
CallbackTraceSource<Packet const &> m_txTrace;
CallbackTraceSource<Packet const &> m_rxTrace;
CallbackTraceSource<Packet const &> m_dropTrace;
};
} // Namespace ns3

View File

@ -20,7 +20,9 @@
//
// Implement the L3Protocols capability for ns3.
// George F. Riley, Georgia Tech, Fall 2006
#include <sstream>
#include <string>
#include "ns3/composite-trace-resolver.h"
#include "l3-demux.h"
#include "l3-protocol.h"
@ -37,6 +39,23 @@ L3Demux::~L3Demux()
delete i->second;
}
}
TraceResolver *
L3Demux::CreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
for (L3Map_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
{
std::string protValue;
std::ostringstream oss (protValue);
oss << (i->second)->GetProtocolNumber ();
ProtocolTraceType context = (i->second)->GetProtocolNumber ();
resolver->Add (protValue,
MakeCallback (&L3Protocol::CreateTraceResolver, i->second),
context);
}
return resolver;
}
L3Demux* L3Demux::Copy(Node *node) const
{

View File

@ -33,14 +33,19 @@ namespace ns3 {
class L3Protocol;
class Node;
class TraceResolver;
class TraceContext;
class L3Demux
{
public:
typedef int ProtocolTraceType;
L3Demux(Node *node);
virtual ~L3Demux();
L3Demux* Copy(Node *node) const;
TraceResolver *CreateTraceResolver (TraceContext const &context);
// Insert a new protocol
ns3::L3Protocol* Insert(const ns3::L3Protocol&);
// Look up a protocol by protocol number

View File

@ -33,7 +33,7 @@ L3Protocol::L3Protocol(int protocolNumber, int version)
{}
L3Protocol::~L3Protocol ()
{}
int
L3Protocol::GetProtocolNumber (void) const
{

View File

@ -30,7 +30,8 @@ namespace ns3 {
class Packet;
class NetDevice;
class Node;
class TraceResolver;
class TraceContext;
/**
* ::Send is always defined in subclasses.
@ -44,6 +45,8 @@ public:
int GetVersion() const;
virtual L3Protocol* Copy(Node *node) const = 0;
virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
/**
* Lower layer calls this method after calling L3Demux::Lookup
* The ARP subclass needs to know from which NetDevice this

View File

@ -163,6 +163,11 @@ NetDevice::Send(Packet& p, const MacAddress& dest, uint16_t protocolNumber)
}
}
TraceResolver *
NetDevice::CreateTraceResolver (TraceContext const &context)
{
return DoCreateTraceResolver (context);
}
// Receive packet from below
bool

View File

@ -31,6 +31,8 @@ namespace ns3 {
class Ipv4L4Demux;
class Node;
class TraceResolver;
class TraceContext;
/**
* \brief Network layer to device interface
@ -58,6 +60,9 @@ class NetDevice {
*/
NetDevice(Node* node, const MacAddress& addr);
virtual ~NetDevice() {}
TraceResolver *CreateTraceResolver (TraceContext const &context);
/**
* \return the current MacAddress of this interface.
*/
@ -204,6 +209,7 @@ class NetDevice {
* MUST override this method.
*/
virtual bool SendTo (Packet& p, const MacAddress& dest) = 0;
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
Node* m_node;
std::string m_name;
uint16_t m_ifIndex;

79
src/node/node-list.cc Normal file
View File

@ -0,0 +1,79 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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:
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
*/
#include "ns3/array-trace-resolver.h"
#include "ns3/trace-root.h"
#include "node-list.h"
#include "node.h"
namespace ns3 {
void
NodeList::Add (Node *node)
{
GetNodes ()->push_back (node);
}
NodeList::Iterator
NodeList::Begin (void)
{
return GetNodes ()->begin ();
}
NodeList::Iterator
NodeList::End (void)
{
return GetNodes ()->end ();
}
std::vector<Node *> *
NodeList::GetNodes (void)
{
static bool firstTime = true;
if (firstTime)
{
TraceRoot::Register ("nodes", MakeCallback (&NodeList::CreateTraceResolver));
}
static std::vector<Node *> nodes;
return &nodes;
}
uint32_t
NodeList::GetNNodes (void)
{
return GetNodes ()->size ();
}
Node *
NodeList::GetNode (uint32_t n)
{
return (*GetNodes ())[n];
}
TraceResolver *
NodeList::CreateTraceResolver (TraceContext const &context)
{
ArrayTraceResolver<Node> *resolver =
new ArrayTraceResolver<Node>
(context,
MakeCallback (&NodeList::GetNNodes),
MakeCallback (&NodeList::GetNode));
return resolver;
}
}//namespace ns3

58
src/node/node-list.h Normal file
View File

@ -0,0 +1,58 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
* All rights reserved.
*
* 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:
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
*/
#ifndef NODE_LIST_H
#define NODE_LIST_H
#include <vector>
#include <string>
#include "ns3/array-trace-resolver.h"
namespace ns3 {
class Node;
class CallbackBase;
class TraceResolver;
class TraceContext;
class NodeList
{
public:
typedef ArrayTraceResolver<Node>::Index NodeIndex;
typedef std::vector<Node *>::iterator Iterator;
static void Add (Node *node);
static Iterator Begin (void);
static Iterator End (void);
static TraceResolver *CreateTraceResolver (TraceContext const &context);
static Node *GetNode (uint32_t n);
private:
static std::vector<Node *> *GetNodes (void);
static uint32_t GetNNodes (void);
};
}//namespace ns3
#endif /* NODE_LIST_H */

View File

@ -99,6 +99,8 @@ class NetDeviceList;
class Ipv4;
class Udp;
class Arp;
class TraceContext;
class TraceResolver;
class Node {
public:
@ -107,6 +109,8 @@ public:
virtual ~Node();
virtual Node* Copy() const = 0;// Make a copy of this node
virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
uint32_t GetId (void) const;
uint32_t GetSystemId (void) const;
void SetSystemId(uint32_t s);

View File

@ -18,20 +18,20 @@
*/
#include "ns3/debug.h"
#include "ns3/composite-trace-resolver.h"
#include "queue.h"
NS_DEBUG_COMPONENT_DEFINE ("Queue");
namespace ns3 {
Queue::Queue(std::string const &name) :
Queue::Queue() :
m_nBytes(0),
m_nTotalReceivedBytes(0),
m_nPackets(0),
m_nTotalReceivedPackets(0),
m_nTotalDroppedBytes(0),
m_nTotalDroppedPackets(0),
m_name (name)
m_nTotalDroppedPackets(0)
{
NS_DEBUG("Queue::Queue ()");
}
@ -41,6 +41,16 @@ Queue::~Queue()
NS_DEBUG("Queue::~Queue ()");
}
TraceResolver *
Queue::CreateTraceResolver (TraceContext const &context)
{
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
resolver->Add ("enqueue", m_traceEnqueue, Queue::ENQUEUE);
resolver->Add ("dequeue", m_traceDequeue, Queue::DEQUEUE);
resolver->Add ("drop", m_traceDrop, Queue::DROP);
return resolver;
}
bool
Queue::Enqueue (const Packet& p)
{
@ -48,7 +58,7 @@ Queue::Enqueue (const Packet& p)
NS_DEBUG("Queue::Enqueue (): m_traceEnqueue (p)");
m_traceEnqueue (m_name, p);
m_traceEnqueue (p);
bool retval = DoEnqueue (p);
if (retval)
@ -77,7 +87,7 @@ Queue::Dequeue (Packet &p)
NS_DEBUG("Queue::Dequeue (): m_traceDequeue (p)");
const Packet packet = p;
m_traceDequeue (m_name, packet);
m_traceDequeue (packet);
}
return retval;
@ -115,19 +125,6 @@ Queue::IsEmpty (void)
return m_nPackets == 0;
}
void
Queue::QueueRegisterTraces (TraceContainer &container)
{
NS_DEBUG("Queue::RegisterTraces (" << &container << ")");
container.RegisterCallback ("Queue::Enqueue",
&m_traceEnqueue);
container.RegisterCallback ("Queue::Dequeue",
&m_traceDequeue);
container.RegisterCallback ("Queue::Drop",
&m_traceDrop);
}
uint32_t
Queue::GetTotalReceivedBytes (void)
{
@ -182,7 +179,7 @@ Queue::Drop (const Packet& p)
m_nTotalDroppedBytes += p.GetSize ();
NS_DEBUG("Queue::Drop (): m_traceDrop (p)");
m_traceDrop (m_name, p);
m_traceDrop (p);
}
}; // namespace ns3

View File

@ -27,17 +27,25 @@
#include <string>
#include "ns3/packet.h"
#include "ns3/callback-tracer.h"
#include "ns3/trace-container.h"
#include "ns3/callback-trace-source.h"
#include "ns3/trace-resolver.h"
namespace ns3 {
class Queue
{
public:
Queue (std::string const &name);
enum TraceType {
ENQUEUE,
DEQUEUE,
DROP,
};
Queue ();
virtual ~Queue ();
TraceResolver *CreateTraceResolver (TraceContext const &context);
bool IsEmpty (void);
bool Enqueue (const Packet& p);
bool Dequeue (Packet &p);
@ -45,8 +53,6 @@ public:
uint32_t GetNPackets (void);
uint32_t GetNBytes (void);
bool IsEmpty (void);
uint32_t GetTotalReceivedBytes (void);
uint32_t GetTotalReceivedPackets (void);
uint32_t GetTotalDroppedBytes (void);
@ -85,12 +91,11 @@ private:
protected:
// called by subclasses to notify parent of packet drops.
void Drop (const Packet& p);
void QueueRegisterTraces (TraceContainer &container);
private:
CallbackTracer<std::string const &, const Packet &> m_traceEnqueue;
CallbackTracer<std::string const &, const Packet &> m_traceDequeue;
CallbackTracer<std::string const &, const Packet &> m_traceDrop;
CallbackTraceSource<const Packet &> m_traceEnqueue;
CallbackTraceSource<const Packet &> m_traceDequeue;
CallbackTraceSource<const Packet &> m_traceDrop;
uint32_t m_nBytes;
uint32_t m_nTotalReceivedBytes;
@ -99,9 +104,6 @@ private:
uint32_t m_nTotalDroppedBytes;
uint32_t m_nTotalDroppedPackets;
std::string m_name;
#if 0
// Static methods to manage queue default
// Set desired queue default

View File

@ -21,6 +21,8 @@
#include "ns3/assert.h"
#include "ns3/packet.h"
#include "ns3/empty-trace-resolver.h"
#include "udp.h"
#include "udp-header.h"
#include "ipv4-end-point-demux.h"
@ -46,6 +48,12 @@ Udp::~Udp ()
delete m_endPoints;
}
TraceResolver *
Udp::CreateTraceResolver (TraceContext const &context)
{
return new EmptyTraceResolver (context);
}
UdpEndPoint *
Udp::Allocate (void)
{

View File

@ -33,6 +33,8 @@
namespace ns3 {
class Node;
class TraceResolver;
class TraceContext;
class Udp : public Ipv4L4Protocol {
public:
@ -41,6 +43,8 @@ public:
Udp (Node *node);
virtual ~Udp ();
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
UdpEndPoint *Allocate (void);
UdpEndPoint *Allocate (Ipv4Address address);
UdpEndPoint *Allocate (uint16_t port);

View File

@ -151,11 +151,11 @@ public:
static void StopAt (Time const &time);
/**
* Schedule an event to expire when time is reached.
* When the event expires, the input method will be invoked
* on the input object.
* Schedule an event to expire when the time "now + time"
* is reached. When the event expires, the input method
* will be invoked on the input object.
*
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @returns an id for the scheduled event.
@ -163,7 +163,7 @@ public:
template <typename T>
static EventId Schedule (Time const &time, void (T::*mem_ptr) (void), T *obj);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
@ -172,7 +172,7 @@ public:
template <typename T, typename T1>
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), T* obj, T1 a1);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
@ -182,7 +182,7 @@ public:
template <typename T, typename T1, typename T2>
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
@ -193,7 +193,7 @@ public:
template <typename T, typename T1, typename T2, typename T3>
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
@ -205,7 +205,7 @@ public:
template <typename T, typename T1, typename T2, typename T3, typename T4>
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
@ -219,13 +219,13 @@ public:
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param f the function to invoke
* @returns an id for the scheduled event.
*/
static EventId Schedule (Time const &time, void (*f) (void));
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param f the function to invoke
* @param a1 the first argument to pass to the function to invoke
* @returns an id for the scheduled event.
@ -233,7 +233,7 @@ public:
template <typename T1>
static EventId Schedule (Time const &time, void (*f) (T1), T1 a1);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param f the function to invoke
* @param a1 the first argument to pass to the function to invoke
* @param a2 the second argument to pass to the function to invoke
@ -242,7 +242,7 @@ public:
template <typename T1, typename T2>
static EventId Schedule (Time const &time, void (*f) (T1,T2), T1 a1, T2 a2);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param f the function to invoke
* @param a1 the first argument to pass to the function to invoke
* @param a2 the second argument to pass to the function to invoke
@ -252,7 +252,7 @@ public:
template <typename T1, typename T2, typename T3>
static EventId Schedule (Time const &time, void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param f the function to invoke
* @param a1 the first argument to pass to the function to invoke
* @param a2 the second argument to pass to the function to invoke
@ -263,7 +263,7 @@ public:
template <typename T1, typename T2, typename T3, typename T4>
static EventId Schedule (Time const &time, void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4);
/**
* @param time the expiration time of the event.
* @param time the relative expiration time of the event.
* @param f the function to invoke
* @param a1 the first argument to pass to the function to invoke
* @param a2 the second argument to pass to the function to invoke