From 327949573da3c59ed8fbdf942dfb7516619fe223 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 18 Mar 2007 14:06:51 -0700 Subject: [PATCH] move channel.cc channel.h to node directory; merge ns-3-tracing from mathieu --- SConstruct | 39 ++- samples/main-serial-net-device-if.cc | 107 ++++-- samples/main-trace.cc | 4 +- samples/ns-2/simple.cc | 107 +++--- src/common/array-trace-resolver.h | 138 ++++++++ src/common/callback-trace-source.cc | 95 +++++ src/common/callback-trace-source.h | 163 +++++++++ src/common/callback-tracer.h | 111 ------ src/common/composite-trace-resolver.cc | 331 ++++++++++++++++++ src/common/composite-trace-resolver.h | 211 +++++++++++ src/common/empty-trace-resolver.cc | 25 ++ src/common/empty-trace-resolver.h | 52 +++ ...{f-variable-tracer.h => fv-trace-source.h} | 28 +- ...si-variable-tracer.h => sv-trace-source.h} | 98 +++--- src/common/terminal-trace-resolver.h | 66 ++++ src/common/trace-container.cc | 188 ---------- src/common/trace-container.h | 312 ----------------- src/common/trace-context.cc | 320 +++++++++++++++++ src/common/trace-context.h | 167 +++++++++ src/common/trace-resolver.cc | 104 ++++++ src/common/trace-resolver.h | 119 +++++++ src/common/trace-root.cc | 54 +++ src/common/trace-root.h | 255 ++++++++++++++ ...ui-variable-tracer.h => uv-trace-source.h} | 99 +++--- src/common/variable-tracer-test.cc | 19 +- src/core/callback-test.cc | 23 +- src/core/callback.h | 84 ++++- src/core/fatal-error.h | 3 +- src/devices/p2p/p2p-net-device.cc | 7 + src/devices/p2p/p2p-net-device.h | 2 + src/devices/serial/serial-channel.cc | 46 ++- src/devices/serial/serial-channel.h | 23 +- src/devices/serial/serial-net-device.cc | 22 +- src/devices/serial/serial-net-device.h | 7 +- src/devices/serial/serial-phy.cc | 35 +- src/devices/serial/serial-phy.h | 17 +- src/node/arp-ipv4-interface.cc | 15 + src/node/arp-ipv4-interface.h | 5 + src/node/arp.cc | 7 + src/node/arp.h | 4 + src/{devices/serial => node}/channel.cc | 4 +- src/{devices/serial => node}/channel.h | 17 +- src/node/drop-tail.cc | 25 +- src/node/drop-tail.h | 3 - src/node/internet-node.cc | 18 + src/node/internet-node.h | 6 + src/node/ipv4-interface.cc | 6 + src/node/ipv4-interface.h | 4 + src/node/ipv4-l4-demux.cc | 19 + src/node/ipv4-l4-demux.h | 4 + src/node/ipv4-l4-protocol.h | 3 + src/node/ipv4-loopback-interface.cc | 13 + src/node/ipv4-loopback-interface.h | 1 + src/node/ipv4.cc | 40 ++- src/node/ipv4.h | 20 +- src/node/l3-demux.cc | 21 +- src/node/l3-demux.h | 5 + src/node/l3-protocol.cc | 2 +- src/node/l3-protocol.h | 5 +- src/node/net-device.cc | 5 + src/node/net-device.h | 6 + src/node/node-list.cc | 79 +++++ src/node/node-list.h | 58 +++ src/node/node.h | 4 + src/node/queue.cc | 35 +- src/node/queue.h | 26 +- src/node/udp.cc | 8 + src/node/udp.h | 4 + src/simulator/simulator.h | 30 +- 69 files changed, 3001 insertions(+), 982 deletions(-) create mode 100644 src/common/array-trace-resolver.h create mode 100644 src/common/callback-trace-source.cc create mode 100644 src/common/callback-trace-source.h delete mode 100644 src/common/callback-tracer.h create mode 100644 src/common/composite-trace-resolver.cc create mode 100644 src/common/composite-trace-resolver.h create mode 100644 src/common/empty-trace-resolver.cc create mode 100644 src/common/empty-trace-resolver.h rename src/common/{f-variable-tracer.h => fv-trace-source.h} (65%) rename src/common/{si-variable-tracer.h => sv-trace-source.h} (58%) create mode 100644 src/common/terminal-trace-resolver.h delete mode 100644 src/common/trace-container.cc delete mode 100644 src/common/trace-container.h create mode 100644 src/common/trace-context.cc create mode 100644 src/common/trace-context.h create mode 100644 src/common/trace-resolver.cc create mode 100644 src/common/trace-resolver.h create mode 100644 src/common/trace-root.cc create mode 100644 src/common/trace-root.h rename src/common/{ui-variable-tracer.h => uv-trace-source.h} (59%) rename src/{devices/serial => node}/channel.cc (95%) rename src/{devices/serial => node}/channel.h (85%) create mode 100644 src/node/node-list.cc create mode 100644 src/node/node-list.h diff --git a/SConstruct b/SConstruct index db9040c4a..3d45caeae 100644 --- a/SConstruct +++ b/SConstruct @@ -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') diff --git a/samples/main-serial-net-device-if.cc b/samples/main-serial-net-device-if.cc index 202e43945..a72c20616 100644 --- a/samples/main-serial-net-device-if.cc +++ b/samples/main-serial-net-device-if.cc @@ -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; } diff --git a/samples/main-trace.cc b/samples/main-trace.cc index 8a888e38c..d3757e65f 100644 --- a/samples/main-trace.cc +++ b/samples/main-trace.cc @@ -9,10 +9,10 @@ using namespace ns3; -CallbackTracer a; +CallbackTraceSourcer a; UiVariableTracer b; StreamTracer c; -CallbackTracer d; +CallbackTraceSourcer d; void RegisterAllTraceSources (TraceContainer *container) diff --git a/samples/ns-2/simple.cc b/samples/ns-2/simple.cc index 624e1ca4e..09260e413 100644 --- a/samples/ns-2/simple.cc +++ b/samples/ns-2/simple.cc @@ -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); diff --git a/src/common/array-trace-resolver.h b/src/common/array-trace-resolver.h new file mode 100644 index 000000000..5a80ad92a --- /dev/null +++ b/src/common/array-trace-resolver.h @@ -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 + */ +#ifndef ARRAY_TRACE_RESOLVER_H +#define ARRAY_TRACE_RESOLVER_H + +#include +#include +#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 +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 getSize, + Callback get); +private: + virtual TraceResolverList DoLookup (std::string id) const; + Callback m_getSize; + Callback m_get; +}; + +}//namespace ns3 + +namespace ns3 { + +template +ArrayTraceResolver::Index::Index () + : m_index () +{} +template +ArrayTraceResolver::Index::Index (uint32_t index) + : m_index (index) +{} +template +ArrayTraceResolver::Index::operator uint32_t () +{ + return m_index; +} + +template +ArrayTraceResolver::ArrayTraceResolver (TraceContext const &context, + Callback getSize, + Callback get) + : TraceResolver (context), + m_getSize (getSize), + m_get (get) +{} +template +TraceResolver::TraceResolverList +ArrayTraceResolver::DoLookup (std::string id) const +{ + TraceResolverList list; + if (id == "*") + { + for (uint32_t i = 0; i < m_getSize (); i++) + { + TraceContext context = GetContext (); + typename ArrayTraceResolver::Index index = typename ArrayTraceResolver::Index (i); + context.Add (index); + list.push_back (m_get (i)->CreateTraceResolver (context)); + } + } + return list; +} + + +}//namespace ns3 + +#endif /* ARRAY_TRACE_RESOLVER_H */ diff --git a/src/common/callback-trace-source.cc b/src/common/callback-trace-source.cc new file mode 100644 index 000000000..d35b4f860 --- /dev/null +++ b/src/common/callback-trace-source.cc @@ -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 + */ +#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 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 diff --git a/src/common/callback-trace-source.h b/src/common/callback-trace-source.h new file mode 100644 index 000000000..ccba70e32 --- /dev/null +++ b/src/common/callback-trace-source.h @@ -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 + */ + +#ifndef CALLBACK_TRACE_H +#define CALLBACK_TRACE_H + +#include +#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 +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 > CallbackList; + TraceContext m_context; + CallbackList m_callbackList; +}; + +}; // namespace ns3 + +// implementation below. + +namespace ns3 { + +template +CallbackTraceSource::CallbackTraceSource () + : m_callbackList () +{} +template +void +CallbackTraceSource::AddCallback (CallbackBase const & callback, + TraceContext const &context) +{ + Callback 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 const *> (&callback); + m_callbackList.push_back (cb); +} +template +void +CallbackTraceSource::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 +void +CallbackTraceSource::operator() (void) +{ + for (typename CallbackList::iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context); + } +} +template +void +CallbackTraceSource::operator() (T1 a1) +{ + for (typename CallbackList::iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1); + } +} +template +void +CallbackTraceSource::operator() (T1 a1, T2 a2) +{ + for (typename CallbackList::iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1, a2); + } +} +template +void +CallbackTraceSource::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 +void +CallbackTraceSource::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 */ diff --git a/src/common/callback-tracer.h b/src/common/callback-tracer.h deleted file mode 100644 index 27ff676df..000000000 --- a/src/common/callback-tracer.h +++ /dev/null @@ -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 - */ - -#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 -class CallbackTracer : public CallbackTracerBase { -public: - CallbackTracer () - : m_callback () {} - void SetCallback (Callback 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 m_callback; -}; - -}; // namespace ns3 - -#endif /* CALLBACK_TRACER_H */ diff --git a/src/common/composite-trace-resolver.cc b/src/common/composite-trace-resolver.cc new file mode 100644 index 000000000..2fef9080b --- /dev/null +++ b/src/common/composite-trace-resolver.cc @@ -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 + */ +#include "composite-trace-resolver.h" + +namespace ns3 { + +CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context) + : TraceResolver (context) +{} + +CompositeTraceResolver::~CompositeTraceResolver () +{} + +void +CompositeTraceResolver::DoAdd (std::string name, + Callback 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 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::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 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 traceDoubleA; + CallbackTraceSource 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 */ diff --git a/src/common/composite-trace-resolver.h b/src/common/composite-trace-resolver.h new file mode 100644 index 000000000..637d04330 --- /dev/null +++ b/src/common/composite-trace-resolver.h @@ -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 + */ +#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 + void Add (std::string name, + CallbackTraceSource &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 + void Add (std::string name, + SVTraceSource &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 + void Add (std::string name, + UVTraceSource &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 + void Add (std::string name, + FVTraceSource &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 + void Add (std::string name, + Callback createResolver, + T const &context); +private: + template + void DoAddTraceSource (std::string name, + SOURCE &traceSource, CONTEXT const &context); + template + static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace, + TraceContext const &context); + void DoAdd (std::string name, + Callback createResolver, + TraceContext const &context); + virtual TraceResolverList DoLookup (std::string id) const; + + struct CallbackTraceSourceItem + { + std::string name; + Callback createResolver; + TraceContext context; + }; + + typedef std::list TraceItems; + TraceItems m_items; +}; + +}//namespace ns3 + +namespace ns3 { + +template +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; + Callback createResolver = + MakeBoundCallback (create, &traceSource); + DoAdd (name, createResolver, traceContext); +} + +template +TraceResolver * +CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource, + TraceContext const &context) +{ + return new TerminalTraceResolver (*traceSource, context); +} + + + + +template +void +CompositeTraceResolver::Add (std::string name, + CallbackTraceSource &trace, + T const &context) +{ + DoAddTraceSource (name, trace, context); +} +template +void +CompositeTraceResolver::Add (std::string name, + SVTraceSource &trace, T const &context) +{ + DoAddTraceSource (name, trace, context); +} +template +void +CompositeTraceResolver::Add (std::string name, + UVTraceSource &trace, T const &context) +{ + DoAddTraceSource (name, trace, context); +} +template +void +CompositeTraceResolver::Add (std::string name, + FVTraceSource &trace, T const &context) +{ + DoAddTraceSource (name, trace, context); +} +template +void +CompositeTraceResolver::Add (std::string name, + Callback createResolver, + T const &context) +{ + TraceContext traceContext = GetContext (); + traceContext.Add (context); + DoAdd (name, createResolver, traceContext); +} + + +}//namespace ns3 + +#endif /* COMPOSITE_TRACE_RESOLVER_H */ diff --git a/src/common/empty-trace-resolver.cc b/src/common/empty-trace-resolver.cc new file mode 100644 index 000000000..18b9e5301 --- /dev/null +++ b/src/common/empty-trace-resolver.cc @@ -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 + */ +#include "empty-trace-resolver.h" + +ns3::EmptyTraceResolver::EmptyTraceResolver (TraceContext const &context) + : TraceResolver (context) +{} diff --git a/src/common/empty-trace-resolver.h b/src/common/empty-trace-resolver.h new file mode 100644 index 000000000..04f1c1bc4 --- /dev/null +++ b/src/common/empty-trace-resolver.h @@ -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 + */ +#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 */ diff --git a/src/common/f-variable-tracer.h b/src/common/fv-trace-source.h similarity index 65% rename from src/common/f-variable-tracer.h rename to src/common/fv-trace-source.h index 4e2353e3c..2e059303b 100644 --- a/src/common/f-variable-tracer.h +++ b/src/common/fv-trace-source.h @@ -22,29 +22,32 @@ #ifndef F_VARIABLE_TRACER_H #define F_VARIABLE_TRACER_H -#include "ns3/callback.h" +#include "callback-trace-source.h" #include namespace ns3 { -class FVariableTracerBase { +class FVTraceSourceBase { public: - typedef Callback ChangeNotifyCallback; + typedef CallbackTraceSource 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 +class FVTraceSource : public FVTraceSourceBase +{ +public: +}; }; // namespace ns3 diff --git a/src/common/si-variable-tracer.h b/src/common/sv-trace-source.h similarity index 58% rename from src/common/si-variable-tracer.h rename to src/common/sv-trace-source.h index 512a69189..56f33289c 100644 --- a/src/common/si-variable-tracer.h +++ b/src/common/sv-trace-source.h @@ -19,32 +19,35 @@ * Author: Mathieu Lacage */ -#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 namespace ns3 { -class SiVariableTracerBase { +class SVTraceSourceBase { public: - typedef Callback ChangeNotifyCallback; + typedef CallbackTraceSource 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 -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 : + * ns3::UVTraceSource : \code #include - #include "ns3/si-traced-variable.tcc" + #include "ns3/sv-trace-source.h" - ns3::SiVariableTracer var; + ns3::SVTraceSource var; \endcode * and you would use it like any other variable of type int32_t: \code @@ -82,44 +86,44 @@ class UiVariableTracer; \endcode */ template -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 - SiVariableTracer &operator = (SiVariableTracer const &o) { + SVTraceSource &operator = (SVTraceSource const &o) { Assign (o.Get ()); return *this; } template - SiVariableTracer &operator = (UiVariableTracer const &o) { + SVTraceSource &operator = (UVTraceSource 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 -SiVariableTracer &operator += (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator += (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () + rhs.Get ()); return lhs; } template -SiVariableTracer &operator -= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator -= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () - rhs.Get ()); return lhs; } template -SiVariableTracer &operator *= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator *= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () * rhs.Get ()); return lhs; } template -SiVariableTracer &operator /= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator /= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () / rhs.Get ()); return lhs; } template -SiVariableTracer &operator <<= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator <<= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () << rhs.Get ()); return lhs; } template -SiVariableTracer &operator >>= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator >>= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () >> rhs.Get ()); return lhs; } template -SiVariableTracer &operator &= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator &= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () & rhs.Get ()); return lhs; } template -SiVariableTracer &operator |= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator |= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () | rhs.Get ()); return lhs; } template -SiVariableTracer &operator ^= (SiVariableTracer &lhs, SiVariableTracer const &rhs) { +SVTraceSource &operator ^= (SVTraceSource &lhs, SVTraceSource const &rhs) { lhs.Assign (lhs.Get () ^ rhs.Get ()); return lhs; } template -SiVariableTracer &operator += (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator += (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () + rhs); return lhs; } template -SiVariableTracer &operator -= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator -= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () - rhs); return lhs; } template -SiVariableTracer &operator *= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator *= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () * rhs); return lhs; } template -SiVariableTracer &operator /= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator /= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () / rhs); return lhs; } template -SiVariableTracer &operator <<= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator <<= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () << rhs); return lhs; } template -SiVariableTracer &operator >>= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator >>= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () >> rhs); return lhs; } template -SiVariableTracer &operator &= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator &= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () & rhs); return lhs; } template -SiVariableTracer &operator |= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator |= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () | rhs); return lhs; } template -SiVariableTracer &operator ^= (SiVariableTracer &lhs, U const &rhs) { +SVTraceSource &operator ^= (SVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () ^ rhs); return lhs; } }; // namespace ns3 -#endif /* SI_VARIABLE_TRACER_H */ +#endif /* SV_TRACE_SOURCE_H */ diff --git a/src/common/terminal-trace-resolver.h b/src/common/terminal-trace-resolver.h new file mode 100644 index 000000000..e026d07cb --- /dev/null +++ b/src/common/terminal-trace-resolver.h @@ -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 + */ +#ifndef TERMINAL_TRACE_RESOLVER_H +#define TERMINAL_TRACE_RESOLVER_H + +#include "trace-resolver.h" + +namespace ns3 { + +class TraceContext; + +template +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 +TerminalTraceResolver::TerminalTraceResolver (T &traceSource, + TraceContext const &context) + : TraceResolver (context), + m_traceSource (traceSource) +{} +template +void +TerminalTraceResolver::DoConnect (CallbackBase const &cb) +{ + m_traceSource.AddCallback (cb, GetContext ()); +} +template +void +TerminalTraceResolver::DoDisconnect (CallbackBase const &cb) +{ + m_traceSource.RemoveCallback (cb); +} + +}//namespace ns3 + +#endif /* TERMINAL_TRACE_RESOLVER_H */ diff --git a/src/common/trace-container.cc b/src/common/trace-container.cc deleted file mode 100644 index 154b40c32..000000000 --- a/src/common/trace-container.cc +++ /dev/null @@ -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 - */ - -#include "trace-container.h" -#include "stream-tracer.h" -#include -#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 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 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 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 -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 << "\""<second << "\""< - */ - -#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 -#include - -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 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 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 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 - */ - template - void SetCallback (std::string const &name, Callback 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 - */ - template - void SetCallback (std::string const &name, Callback 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 - */ - template - void SetCallback (std::string const &name, Callback 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 - */ - template - void SetCallback (std::string const&name, Callback 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 - */ - template - void SetCallback (std::string const &name, Callback 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 > UiList; - typedef std::list >::iterator UiListI; - typedef std::list > SiList; - typedef std::list >::iterator SiListI; - typedef std::list > FList; - typedef std::list >::iterator FListI; - typedef std::list > StreamTracerList; - typedef std::list >::iterator StreamTracerListI; - typedef std::list > CallbackList; - typedef std::list >::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 -void -TraceContainer::SetCallback (std::string const&name, Callback callback) -{ - for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) - { - if (i->second == name) - { - if (i->first->CheckCallbackType (callback)) - { - static_cast *> (i->first)->SetCallback (callback); - return; - } - else - { - NS_ASSERT (!"non-matching callback"); - } - } - } - NS_ASSERT (false); -} -template -void -TraceContainer::SetCallback (std::string const&name, Callback callback) -{ - for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) - { - if (i->second == name) - { - if (i->first->CheckCallbackType (callback)) - { - static_cast *> (i->first)->SetCallback (callback); - return; - } - else - { - NS_ASSERT (!"non-matching callback"); - } - } - } - NS_ASSERT (false); -} -template -void -TraceContainer::SetCallback (std::string const&name, Callback callback) -{ - for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) - { - if (i->second == name) - { - if (i->first->CheckCallbackType (callback)) - { - static_cast *> (i->first)->SetCallback (callback); - return; - } - else - { - NS_ASSERT (!"non-matching callback"); - } - } - } - NS_ASSERT (false); -} -template -void -TraceContainer::SetCallback (std::string const&name, Callback callback) -{ - for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) - { - if (i->second == name) - { - if (i->first->CheckCallbackType (callback)) - { - static_cast *> (i->first)->SetCallback (callback); - return; - } - else - { - NS_ASSERT (!"non-matching callback"); - } - } - } - NS_ASSERT (false); -} -template -void -TraceContainer::SetCallback (std::string const&name, Callback callback) -{ - for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) - { - if (i->second == name) - { - if (i->first->CheckCallbackType (callback)) - { - static_cast *> (i->first)->SetCallback (callback); - return; - } - else - { - NS_ASSERT (!"non-matching callback"); - } - } - } - NS_ASSERT (false); -} - - -}; // namespace ns3 - -#endif /* TRACED_VARIABLE_CONTAINER_H */ diff --git a/src/common/trace-context.cc b/src/common/trace-context.cc new file mode 100644 index 000000000..786ce9149 --- /dev/null +++ b/src/common/trace-context.cc @@ -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 + */ +#include "trace-context.h" +#include "ns3/assert.h" + +namespace ns3 { + +std::vector 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 +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 diff --git a/src/common/trace-context.h b/src/common/trace-context.h new file mode 100644 index 000000000..a22e2cba3 --- /dev/null +++ b/src/common/trace-context.h @@ -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 + */ +#ifndef TRACE_CONTEXT_H +#define TRACE_CONTEXT_H + +#include +#include +#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 + 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 + void Get (T &context) const; +private: + friend class TraceContextTest; + // used exclusively for testing code. + template + bool SafeGet (T &context) const; + template + bool SafeAdd (T &context); + + template + static uint8_t GetUid (void); + template + 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 m_sizes; + struct Data { + uint16_t count; + uint16_t size; + uint8_t data[4]; + } * m_data; +}; + +}//namespace ns3 + +namespace ns3 { + +template +void +TraceContext::Add (T const &context) +{ + uint8_t *data = (uint8_t *) &context; + bool ok = DoAdd (TraceContext::GetUid (), data); + if (!ok) + { + NS_FATAL_ERROR ("Trying to add twice the same type with different values is invalid."); + } +} +template +void +TraceContext::Get (T &context) const +{ + uint8_t *data = (uint8_t *) &context; + bool found = DoGet (TraceContext::GetUid (), data); + if (!found) + { + NS_FATAL_ERROR ("Type not stored in TraceContext"); + } +} +template +bool +TraceContext::SafeGet (T &context) const +{ + uint8_t *data = (uint8_t *) &context; + bool found = DoGet (TraceContext::GetUid (), data); + return found; +} +template +bool +TraceContext::SafeAdd (T &context) +{ + uint8_t *data = (uint8_t *) &context; + bool ok = DoAdd (TraceContext::GetUid (), data); + return ok; +} +template +uint8_t +TraceContext::GetUid (void) +{ + static uint8_t uid = GetNextUid (); + return uid; +} + +template +uint8_t +TraceContext::GetNextUid (void) +{ + uint8_t uid = DoGetNextUid (); + m_sizes.push_back (sizeof (T)); + return uid; +} + +}//namespace ns3 + +#endif /* TRACE_CONTEXT_H */ diff --git a/src/common/trace-resolver.cc b/src/common/trace-resolver.cc new file mode 100644 index 000000000..251e7cc87 --- /dev/null +++ b/src/common/trace-resolver.cc @@ -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 + */ +#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 diff --git a/src/common/trace-resolver.h b/src/common/trace-resolver.h new file mode 100644 index 000000000..68011f84f --- /dev/null +++ b/src/common/trace-resolver.h @@ -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 + */ +#ifndef TRACE_RESOLVER_H +#define TRACE_RESOLVER_H + +#include +#include +#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 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 */ diff --git a/src/common/trace-root.cc b/src/common/trace-root.cc new file mode 100644 index 000000000..3862408f4 --- /dev/null +++ b/src/common/trace-root.cc @@ -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 + */ +#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 createResolver) +{ + CompositeTraceResolver *resolver = GetComposite (); + resolver->Add (name, createResolver, TraceRoot::NOTHING); +} + +CompositeTraceResolver * +TraceRoot::GetComposite (void) +{ + static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ()); + return &resolver; +} + +} // namespace ns3 diff --git a/src/common/trace-root.h b/src/common/trace-root.h new file mode 100644 index 000000000..f5187e4a6 --- /dev/null +++ b/src/common/trace-root.h @@ -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 + */ +#ifndef TRACE_ROOT_H +#define TRACE_ROOT_H + +#include +#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 createResolver); +private: + static CompositeTraceResolver *GetComposite (void); + enum TraceType { + NOTHING, + }; +}; + +}// namespace ns3 + +#endif /* TRACE_ROOT_H */ diff --git a/src/common/ui-variable-tracer.h b/src/common/uv-trace-source.h similarity index 59% rename from src/common/ui-variable-tracer.h rename to src/common/uv-trace-source.h index dd0cdb083..45c77da91 100644 --- a/src/common/ui-variable-tracer.h +++ b/src/common/uv-trace-source.h @@ -19,35 +19,39 @@ * Author: Mathieu Lacage */ -#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 namespace ns3 { -class UiVariableTracerBase { +class UVTraceSourceBase { public: - typedef Callback ChangeNotifyCallback; + typedef CallbackTraceSource 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 -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 : + * ns3::UVTraceSource : \code #include - #include "ns3/ui-traced-variable.tcc" + #include "ns3/uv-trace-source.h" - ns3::UiVariableTracer var; + ns3::UVTraceSource var; \endcode * and you would use it like any other variable of type uint32_t: \code @@ -84,44 +89,44 @@ class SiVariableTracer; \endcode */ template -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 - UiVariableTracer &operator = (UiVariableTracer const &o) { + UVTraceSource &operator = (UVTraceSource const &o) { Assign (o.Get ()); return *this; } template - UiVariableTracer &operator = (SiVariableTracer const &o) { + UVTraceSource &operator = (SVTraceSource 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 -UiVariableTracer &operator += (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator += (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () + rhs.Get ()); return lhs; } template -UiVariableTracer &operator -= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator -= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () - rhs.Get ()); return lhs; } template -UiVariableTracer &operator *= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator *= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () * rhs.Get ()); return lhs; } template -UiVariableTracer &operator /= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator /= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () / rhs.Get ()); return lhs; } template -UiVariableTracer &operator <<= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator <<= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () << rhs.Get ()); return lhs; } template -UiVariableTracer &operator >>= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator >>= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () >> rhs.Get ()); return lhs; } template -UiVariableTracer &operator &= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator &= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () & rhs.Get ()); return lhs; } template -UiVariableTracer &operator |= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator |= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () | rhs.Get ()); return lhs; } template -UiVariableTracer &operator ^= (UiVariableTracer &lhs, UiVariableTracer const &rhs) { +UVTraceSource &operator ^= (UVTraceSource &lhs, UVTraceSource const &rhs) { lhs.Assign (lhs.Get () ^ rhs.Get ()); return lhs; } template -UiVariableTracer &operator += (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator += (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () + rhs); return lhs; } template -UiVariableTracer &operator -= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator -= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () - rhs); return lhs; } template -UiVariableTracer &operator *= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator *= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () * rhs); return lhs; } template -UiVariableTracer &operator /= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator /= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () / rhs); return lhs; } template -UiVariableTracer &operator <<= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator <<= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () << rhs); return lhs; } template -UiVariableTracer &operator >>= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator >>= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () >> rhs); return lhs; } template -UiVariableTracer &operator &= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator &= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () & rhs); return lhs; } template -UiVariableTracer &operator |= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator |= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () | rhs); return lhs; } template -UiVariableTracer &operator ^= (UiVariableTracer &lhs, U const &rhs) { +UVTraceSource &operator ^= (UVTraceSource &lhs, U const &rhs) { lhs.Assign (lhs.Get () ^ rhs); return lhs; } }; // namespace ns3 -#endif /* UI_VARIABLE_TRACER_H */ +#endif /* UV_TRACE_SOURCE_H */ diff --git a/src/common/variable-tracer-test.cc b/src/common/variable-tracer-test.cc index d0a5ad3cf..29f3fc148 100644 --- a/src/common/variable-tracer-test.cc +++ b/src/common/variable-tracer-test.cc @@ -19,8 +19,9 @@ * Author: Mathieu Lacage */ -#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 var, ovar, tmp; + UVTraceSource 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 uvar = 10; - UiVariableTracer uivar = 5; - SiVariableTracer svar = 5; - SiVariableTracer sivar = 5; + UVTraceSource uvar = 10; + UVTraceSource uivar = 5; + SVTraceSource svar = 5; + SVTraceSource sivar = 5; uvar = svar; svar = uvar; uvar += svar; diff --git a/src/core/callback-test.cc b/src/core/callback-test.cc index 54ee88b5b..4cc1b77fb 100644 --- a/src/core/callback-test.cc +++ b/src/core/callback-test.cc @@ -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; } diff --git a/src/core/callback.h b/src/core/callback.h index 0f383cc28..5932ae919 100644 --- a/src/core/callback.h +++ b/src/core/callback.h @@ -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 const *otherDerived = + dynamic_cast 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 const *otherDerived = + dynamic_cast 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 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 - Callback (FUNCTOR const &functor) + Callback (FUNCTOR const &functor, bool, bool) : m_impl (new FunctorCallbackImpl (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 *> (otherBase) != 0) @@ -351,7 +386,7 @@ Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5), OBJ */ template Callback MakeCallback (R (*fnPtr) ()) { - return Callback (fnPtr); + return Callback (fnPtr, true, true); } /** * \ingroup MakeCallback @@ -362,7 +397,7 @@ Callback MakeCallback (R (*fnPtr) ()) { */ template Callback MakeCallback (R (*fnPtr) (T1)) { - return Callback (fnPtr); + return Callback (fnPtr, true, true); } /** * \ingroup MakeCallback @@ -373,7 +408,7 @@ Callback MakeCallback (R (*fnPtr) (T1)) { */ template Callback MakeCallback (R (*fnPtr) (T1,T2)) { - return Callback (fnPtr); + return Callback (fnPtr, true, true); } /** * \ingroup MakeCallback @@ -384,7 +419,7 @@ Callback MakeCallback (R (*fnPtr) (T1,T2)) { */ template Callback MakeCallback (R (*fnPtr) (T1,T2,T3)) { - return Callback (fnPtr); + return Callback (fnPtr, true, true); } /** * \ingroup MakeCallback @@ -395,7 +430,7 @@ Callback MakeCallback (R (*fnPtr) (T1,T2,T3)) { */ template Callback MakeCallback (R (*fnPtr) (T1,T2,T3,T4)) { - return Callback (fnPtr); + return Callback (fnPtr, true, true); } /** * \ingroup MakeCallback @@ -406,7 +441,7 @@ Callback MakeCallback (R (*fnPtr) (T1,T2,T3,T4)) { */ template Callback MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) { - return Callback (fnPtr); + return Callback (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 const *otherDerived = + dynamic_cast 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 +Callback MakeBoundCallback (R (*fnPtr) (TX), TX a) { + ReferenceList*> impl = + ReferenceList*> ( + new BoundFunctorCallbackImpl (fnPtr, a) + ); + return Callback (impl); +} + template Callback MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) { ReferenceList*> impl = diff --git a/src/core/fatal-error.h b/src/core/fatal-error.h index 0d1a48316..1ca0b8da9 100644 --- a/src/core/fatal-error.h +++ b/src/core/fatal-error.h @@ -22,10 +22,9 @@ #define FATAL_ERROR_H #include "assert.h" -#include /** - * \defgroup error + * \defgroup error Error * \brief fatal error handling * * \param msg message to output when this macro is hit. diff --git a/src/devices/p2p/p2p-net-device.cc b/src/devices/p2p/p2p-net-device.cc index 36bfb343d..fe81c2f64 100644 --- a/src/devices/p2p/p2p-net-device.cc +++ b/src/devices/p2p/p2p-net-device.cc @@ -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) { diff --git a/src/devices/p2p/p2p-net-device.h b/src/devices/p2p/p2p-net-device.h index 380328e01..4809ea738 100644 --- a/src/devices/p2p/p2p-net-device.h +++ b/src/devices/p2p/p2p-net-device.h @@ -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; }; diff --git a/src/devices/serial/serial-channel.cc b/src/devices/serial/serial-channel.cc index 7c0128c18..bbcd75366 100644 --- a/src/devices/serial/serial-channel.cc +++ b/src/devices/serial/serial-channel.cc @@ -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 (p.GetSize() * 8) / - static_cast (m_bps)) + m_delay; + Time tEvent = Seconds (static_cast (p.GetSize() * 8) / + static_cast (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 diff --git a/src/devices/serial/serial-channel.h b/src/devices/serial/serial-channel.h index 41e5b49e3..76d19b0f1 100644 --- a/src/devices/serial/serial-channel.h +++ b/src/devices/serial/serial-channel.h @@ -20,8 +20,7 @@ #define SERIAL_CHANNEL_H #include -#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]; diff --git a/src/devices/serial/serial-net-device.cc b/src/devices/serial/serial-net-device.cc index ee071e854..f62303873 100644 --- a/src/devices/serial/serial-net-device.cc +++ b/src/devices/serial/serial-net-device.cc @@ -23,6 +23,7 @@ #include #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); } } diff --git a/src/devices/serial/serial-net-device.h b/src/devices/serial/serial-net-device.h index 6d77e9c76..91b3c8cca 100644 --- a/src/devices/serial/serial-net-device.h +++ b/src/devices/serial/serial-net-device.h @@ -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; diff --git a/src/devices/serial/serial-phy.cc b/src/devices/serial/serial-phy.cc index f1e6f1277..274e11cbe 100644 --- a/src/devices/serial/serial-phy.cc +++ b/src/devices/serial/serial-phy.cc @@ -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 diff --git a/src/devices/serial/serial-phy.h b/src/devices/serial/serial-phy.h index 00d59f9f0..317a0ce88 100644 --- a/src/devices/serial/serial-phy.h +++ b/src/devices/serial/serial-phy.h @@ -21,22 +21,27 @@ #ifndef SERIAL_PHY_H #define SERIAL_PHY_H -#include -#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; }; diff --git a/src/node/arp-ipv4-interface.cc b/src/node/arp-ipv4-interface.cc index 3287d7dd6..a788e421e 100644 --- a/src/node/arp-ipv4-interface.cc +++ b/src/node/arp-ipv4-interface.cc @@ -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) { diff --git a/src/node/arp-ipv4-interface.h b/src/node/arp-ipv4-interface.h index 9a40789ae..d165c783b 100644 --- a/src/node/arp-ipv4-interface.h +++ b/src/node/arp-ipv4-interface.h @@ -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; }; diff --git a/src/node/arp.cc b/src/node/arp.cc index 3414d1d12..d405f0c6e 100644 --- a/src/node/arp.cc +++ b/src/node/arp.cc @@ -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) { diff --git a/src/node/arp.h b/src/node/arp.h index 4ea17dad6..c940de43f 100644 --- a/src/node/arp.h +++ b/src/node/arp.h @@ -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, diff --git a/src/devices/serial/channel.cc b/src/node/channel.cc similarity index 95% rename from src/devices/serial/channel.cc rename to src/node/channel.cc index 5b1f9a212..690da0ce8 100644 --- a/src/devices/serial/channel.cc +++ b/src/node/channel.cc @@ -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 << ")"); } diff --git a/src/devices/serial/channel.h b/src/node/channel.h similarity index 85% rename from src/devices/serial/channel.h rename to src/node/channel.h index 43d952373..f3f95fa2d 100644 --- a/src/devices/serial/channel.h +++ b/src/node/channel.h @@ -19,16 +19,16 @@ * * Wed Feb 14 16:05:46 PST 2007 craigdo: Created */ - -#include -#include "ns3/packet.h" -#include "layer-connector.h" - #ifndef CHANNEL_H #define CHANNEL_H +#include +#include + 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; diff --git a/src/node/drop-tail.cc b/src/node/drop-tail.cc index 6811304e3..c3dc4f79f 100644 --- a/src/node/drop-tail.cc +++ b/src/node/drop-tail.cc @@ -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 << ")"); diff --git a/src/node/drop-tail.h b/src/node/drop-tail.h index 8d0df68d1..8ac8ab47a 100644 --- a/src/node/drop-tail.h +++ b/src/node/drop-tail.h @@ -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(); diff --git a/src/node/internet-node.cc b/src/node/internet-node.cc index f338f030b..3f902768a 100644 --- a/src/node/internet-node.cc +++ b/src/node/internet-node.cc @@ -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 diff --git a/src/node/internet-node.h b/src/node/internet-node.h index 53407cf1d..b61a23fc5 100644 --- a/src/node/internet-node.h +++ b/src/node/internet-node.h @@ -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; diff --git a/src/node/ipv4-interface.cc b/src/node/ipv4-interface.cc index 1f4f01e5e..98311a2ae 100644 --- a/src/node/ipv4-interface.cc +++ b/src/node/ipv4-interface.cc @@ -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) { diff --git a/src/node/ipv4-interface.h b/src/node/ipv4-interface.h index c74b57890..4968125c7 100644 --- a/src/node/ipv4-interface.h +++ b/src/node/ipv4-interface.h @@ -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; diff --git a/src/node/ipv4-l4-demux.cc b/src/node/ipv4-l4-demux.cc index 6260f457a..3a2b9b986 100644 --- a/src/node/ipv4-l4-demux.cc +++ b/src/node/ipv4-l4-demux.cc @@ -22,6 +22,8 @@ // Define the layer 4 demultiplexer object for ns3. // George F. Riley, Georgia Tech, Fall 2006 +#include +#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) { diff --git a/src/node/ipv4-l4-demux.h b/src/node/ipv4-l4-demux.h index 497c56858..d578366fb 100644 --- a/src/node/ipv4-l4-demux.h +++ b/src/node/ipv4-l4-demux.h @@ -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*); diff --git a/src/node/ipv4-l4-protocol.h b/src/node/ipv4-l4-protocol.h index 58c1a5ce5..efefe449f 100644 --- a/src/node/ipv4-l4-protocol.h +++ b/src/node/ipv4-l4-protocol.h @@ -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. diff --git a/src/node/ipv4-loopback-interface.cc b/src/node/ipv4-loopback-interface.cc index bc23bd18f..5db423d37 100644 --- a/src/node/ipv4-loopback-interface.cc +++ b/src/node/ipv4-loopback-interface.cc @@ -19,6 +19,7 @@ * Authors: * Mathieu Lacage , */ +#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) { diff --git a/src/node/ipv4-loopback-interface.h b/src/node/ipv4-loopback-interface.h index 4913c32ea..476a72abd 100644 --- a/src/node/ipv4-loopback-interface.h +++ b/src/node/ipv4-loopback-interface.h @@ -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; diff --git a/src/node/ipv4.cc b/src/node/ipv4.cc index d996467f7..66b207641 100644 --- a/src/node/ipv4.cc +++ b/src/node/ipv4.cc @@ -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 *resolver = + new ArrayTraceResolver + (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."); diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 59fced43c..1a4a33b63 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -24,6 +24,8 @@ #include #include +#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::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 Ipv4InterfaceList; typedef std::list HostRoutes; @@ -126,6 +141,9 @@ public: NetworkRoutes m_networkRoutes; Ipv4Route *m_defaultRoute; Node *m_node; + CallbackTraceSource m_txTrace; + CallbackTraceSource m_rxTrace; + CallbackTraceSource m_dropTrace; }; } // Namespace ns3 diff --git a/src/node/l3-demux.cc b/src/node/l3-demux.cc index 1d7172bde..091674597 100644 --- a/src/node/l3-demux.cc +++ b/src/node/l3-demux.cc @@ -20,7 +20,9 @@ // // Implement the L3Protocols capability for ns3. // George F. Riley, Georgia Tech, Fall 2006 - +#include +#include +#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 { diff --git a/src/node/l3-demux.h b/src/node/l3-demux.h index 9a8b07cd9..a6843cf3f 100644 --- a/src/node/l3-demux.h +++ b/src/node/l3-demux.h @@ -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 diff --git a/src/node/l3-protocol.cc b/src/node/l3-protocol.cc index 241647bb9..acf841267 100644 --- a/src/node/l3-protocol.cc +++ b/src/node/l3-protocol.cc @@ -33,7 +33,7 @@ L3Protocol::L3Protocol(int protocolNumber, int version) {} L3Protocol::~L3Protocol () {} - + int L3Protocol::GetProtocolNumber (void) const { diff --git a/src/node/l3-protocol.h b/src/node/l3-protocol.h index eebb08a5e..59b41e8f2 100644 --- a/src/node/l3-protocol.h +++ b/src/node/l3-protocol.h @@ -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 diff --git a/src/node/net-device.cc b/src/node/net-device.cc index da2b8cadb..b935bddbb 100644 --- a/src/node/net-device.cc +++ b/src/node/net-device.cc @@ -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 diff --git a/src/node/net-device.h b/src/node/net-device.h index ee05f972d..f2ebb66b6 100644 --- a/src/node/net-device.h +++ b/src/node/net-device.h @@ -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; diff --git a/src/node/node-list.cc b/src/node/node-list.cc new file mode 100644 index 000000000..6fac78d7e --- /dev/null +++ b/src/node/node-list.cc @@ -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 , + */ + +#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 * +NodeList::GetNodes (void) +{ + static bool firstTime = true; + if (firstTime) + { + TraceRoot::Register ("nodes", MakeCallback (&NodeList::CreateTraceResolver)); + } + static std::vector 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 *resolver = + new ArrayTraceResolver + (context, + MakeCallback (&NodeList::GetNNodes), + MakeCallback (&NodeList::GetNode)); + return resolver; +} + +}//namespace ns3 diff --git a/src/node/node-list.h b/src/node/node-list.h new file mode 100644 index 000000000..c954664da --- /dev/null +++ b/src/node/node-list.h @@ -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 , + */ +#ifndef NODE_LIST_H +#define NODE_LIST_H + +#include +#include +#include "ns3/array-trace-resolver.h" + +namespace ns3 { + +class Node; +class CallbackBase; +class TraceResolver; +class TraceContext; + +class NodeList +{ +public: + typedef ArrayTraceResolver::Index NodeIndex; + typedef std::vector::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 *GetNodes (void); + static uint32_t GetNNodes (void); + +}; + +}//namespace ns3 + + +#endif /* NODE_LIST_H */ diff --git a/src/node/node.h b/src/node/node.h index 4b7560d3a..b8ef6278e 100644 --- a/src/node/node.h +++ b/src/node/node.h @@ -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); diff --git a/src/node/queue.cc b/src/node/queue.cc index aa711a5b1..26ba3bbe8 100644 --- a/src/node/queue.cc +++ b/src/node/queue.cc @@ -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 diff --git a/src/node/queue.h b/src/node/queue.h index 43e7acffb..799c682ff 100644 --- a/src/node/queue.h +++ b/src/node/queue.h @@ -27,17 +27,25 @@ #include #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 m_traceEnqueue; - CallbackTracer m_traceDequeue; - CallbackTracer m_traceDrop; + CallbackTraceSource m_traceEnqueue; + CallbackTraceSource m_traceDequeue; + CallbackTraceSource 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 diff --git a/src/node/udp.cc b/src/node/udp.cc index f1f0fef29..0f9b063a6 100644 --- a/src/node/udp.cc +++ b/src/node/udp.cc @@ -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) { diff --git a/src/node/udp.h b/src/node/udp.h index da88a1433..ba6c1dbb0 100644 --- a/src/node/udp.h +++ b/src/node/udp.h @@ -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); diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index 9b67c010b..57d9c8ac5 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -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 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 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 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 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 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 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 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 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 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