merge tracing overhaul in trunk
This commit is contained in:
@@ -6,5 +6,6 @@ build
|
||||
.*\.sconsign
|
||||
doc/html.*
|
||||
doc/latex.*
|
||||
doc/trace-source-list.h
|
||||
.lock-wscript
|
||||
.waf*
|
||||
|
||||
@@ -450,7 +450,7 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = src doc/main.txt
|
||||
INPUT = src doc/main.txt doc/trace-source-list.h doc/tracing.h
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
@@ -514,7 +514,7 @@ EXAMPLE_RECURSIVE = NO
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
IMAGE_PATH = doc
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* - \ref config
|
||||
* - a base class for objects which need to support reference counting
|
||||
* and QueryInterface: ns3::Object and ns3::InterfaceId
|
||||
* - a set of low-level trace facilities integrated in the ns3::Object system: \ref tracing
|
||||
* - a ns3::ComponentManager which can be used to manage the creation
|
||||
* of any object which derives from ns3::Object through an ns3::ClassId
|
||||
* - a smart-pointer class ns3::Ptr designed to work together with ns3::Object
|
||||
@@ -33,11 +34,10 @@
|
||||
* ns3::Scheduler and ns3::SchedulerFactory
|
||||
* - a simulator class used to create, schedule and cancel events: ns3::Simulator
|
||||
*
|
||||
* The "common" module contains:
|
||||
* The "core" module contains:
|
||||
* - a packet class to create and manipulate simulation packets: ns3::Packet, ns3::Header,
|
||||
* and ns3::Trailer. This packet class also supports per-packet ns3::Tag which are
|
||||
* globs of data which can be attached to any packet.
|
||||
* - a set of low-level trace facilities: \ref lowleveltracing
|
||||
*
|
||||
* The "node" module contains:
|
||||
* - a ns3::Node base class which should be subclassed by any new type of
|
||||
|
||||
1658
doc/namespace-2.dia
Normal file
1658
doc/namespace-2.dia
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/namespace-2.png
Normal file
BIN
doc/namespace-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
204
doc/trace-source-list.h
Normal file
204
doc/trace-source-list.h
Normal file
@@ -0,0 +1,204 @@
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief send ipv4 packet to outgoing interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet sent.
|
||||
/// \param arg3 index of output ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/ipv4/tx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback0 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive ipv4 packet from incoming interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
/// \param arg3 index of input ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/ipv4/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback1 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop ipv4 packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/ipv4/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback2 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief store packet in queue
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet queued.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/enqueue.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::QueueTraceType
|
||||
void TraceSinkCallback3 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief remove packet from queue
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dequeued.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/dequeue.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::QueueTraceType
|
||||
void TraceSinkCallback4 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop packet from queue
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::QueueTraceType
|
||||
void TraceSinkCallback5 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive MAC packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::PointToPointTraceType
|
||||
void TraceSinkCallback6 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive MAC packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::CsmaTraceType
|
||||
void TraceSinkCallback7 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop MAC packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::CsmaTraceType
|
||||
void TraceSinkCallback8 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief The value of the speed vector changed
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 the mobility model whose course changed.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$MobilityModelNotifier/course-change.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
void TraceSinkCallback9 (const TraceContext & arg1, Ptr<const MobilityModel> arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief send ipv4 packet to outgoing interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet sent.
|
||||
/// \param arg3 index of output ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/tx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback10 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive ipv4 packet from incoming interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
/// \param arg3 index of input ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback11 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop ipv4 packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback12 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
576
doc/tracing.h
Normal file
576
doc/tracing.h
Normal file
@@ -0,0 +1,576 @@
|
||||
/**
|
||||
* \defgroup TraceSourceList List of trace sources
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup tracing Tracing
|
||||
*
|
||||
* The flexibility of the ns-3 tracing system comes at the cost of quite
|
||||
* a bit of complexity so, before trying to use the low-level aspects
|
||||
* of the tracing API, it is important to focus on some basic definitions:
|
||||
*
|
||||
* - A trace source is an object instance which can report trace events
|
||||
* to a set of listening trace sinks.
|
||||
*
|
||||
* - A trace sink is a user-provided callback (a function) which can
|
||||
* be connected to a set of trace sources to receive the events generated
|
||||
* by each trace source.
|
||||
*
|
||||
* - A trace resolver is an object which allows users to establish
|
||||
* connections between a set of trace sources and a set of trace sinks.
|
||||
*
|
||||
* \section TraceSource Generating Trace Events
|
||||
*
|
||||
* So, what does it look like in practice ? First, let's look at trace
|
||||
* sources. We have two types of trace sources: numeric, and, normal
|
||||
* trace sources. Numeric trace sources behave as normal c++ integers
|
||||
* or c++ floating point numbers except that they report as trace events
|
||||
* each change of their value. For example:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (void)
|
||||
* {
|
||||
* // use the "int" trace source just
|
||||
* // like any other "int" variable.
|
||||
* m_cwnd *= 2;
|
||||
* m_cwnd += 4;
|
||||
* if (m_cwnd > 100)
|
||||
* {
|
||||
* // do something.
|
||||
* }
|
||||
* }
|
||||
* private:
|
||||
* // declare an instance of a "int" trace source
|
||||
* SVTraceSource<int> m_cwnd;
|
||||
* };
|
||||
* \endcode
|
||||
* Normal trace sources, on the other hand, allow you to trace the
|
||||
* call of arbitrary functions and methods, as shown below. They are
|
||||
* typically used to track "rx", "tx", or "drop" events but could
|
||||
* also be used to track route change events, or position change
|
||||
* events:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (Packet packet)
|
||||
* {
|
||||
* // report this event on packet
|
||||
* m_doSomething (packet);
|
||||
* // do something
|
||||
* }
|
||||
* private:
|
||||
* // report every "something" function call.
|
||||
* CallbackTraceSource<Packet> m_doSomething;
|
||||
* };
|
||||
* \endcode
|
||||
* Every type of trace source derives from the ns3::TraceSource base class.
|
||||
* As of today, the set of concrete subclasses is relatively short:
|
||||
* ns3::CallbackTraceSource, ns3::SvTraceSource, ns3::UvTraceSource, and,
|
||||
* ns3::FvTraceSource.
|
||||
*
|
||||
* \section TraceSink Receiving Trace Events
|
||||
*
|
||||
* To receive these trace events, a user should specify a set of trace sinks.
|
||||
* For example, to receive the "int" and the "something" events shown in the
|
||||
* examples above, a user would declare the following functions:
|
||||
* \code
|
||||
* // oldValue and newValue contain the previous and new values of
|
||||
* // the connected SVTraceSource<int> trace source.
|
||||
* void
|
||||
* CwndTraceSink (const TraceContext &context, int64_t oldValue, int64_t newValue)
|
||||
* {
|
||||
* // for example, print the new value:
|
||||
* std::cout << "cwnd=" << newValue << std::endl;
|
||||
* }
|
||||
* void
|
||||
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
|
||||
* {
|
||||
* // for example, print the arguments
|
||||
* std::cout << "packet " << packet << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
* Each of these sink function takes, as a first argument, a reference to a
|
||||
* const TraceContext object. This context object contains information which
|
||||
* describes the instance of the connected trace source: that information is
|
||||
* setup during the connection process and does not change afterwards
|
||||
* The type and the number of the other arguments to each trace sink depends
|
||||
* on the type of the connected trace source: it conveys per-event information
|
||||
* from the trace source to the trace sink. For example, UVTraceSource and
|
||||
* SVTraceSource trace sources require two extra arguments. The former requires
|
||||
* two unsigned 64 bit integers while the latter requires two signed 64 bit
|
||||
* integers. More generally, users can consult the \ref TraceSourceList
|
||||
* to figure out the arguments which a trace sink is required to receive
|
||||
* for each trace source: a signature of the user trace sink must match
|
||||
* _exactly_ the signature documented in the \ref TraceSourceList.
|
||||
*
|
||||
*
|
||||
* \section TraceSourceSimpleExport A simple way to connect Trace Sources with Trace Sinks
|
||||
*
|
||||
* The crux of the complexity of the ns-3 tracing system comes from its
|
||||
* flexible system used to connect trace sources to trace sinks but what is really
|
||||
* nice about it is that it is not necessary to use it to setup simple traces.
|
||||
*
|
||||
* The simplest way to export a set of trace sources to a user, for example,
|
||||
* during the early prototyping phases of a system, is to add a set of public methods
|
||||
* to give to your users access to the trace source object instances you use to generate
|
||||
* trace events:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (Packet packet)
|
||||
* {
|
||||
* // report this event on packet
|
||||
* m_doSomething (packet);
|
||||
* // do something
|
||||
* }
|
||||
* CallbackTraceSource<Packet> *PeekSomethingTraceSource (void) const
|
||||
* {
|
||||
* return &m_doSomething
|
||||
* }
|
||||
* private:
|
||||
* // report every "something" function call.
|
||||
* CallbackTraceSource<Packet> m_doSomething;
|
||||
* };
|
||||
* \endcode
|
||||
* If your users hold a pointer to an instance of MyModel, and if they want to connect
|
||||
* a MySomethingSink, they can simply do the following which invokes the
|
||||
* TraceSource::AddCallback method and creates a Callback object from the user's
|
||||
* sink with the MakeCallback function.
|
||||
* \code
|
||||
* void
|
||||
* MySomethingSink (const TraceContext &context, Packet packet)
|
||||
* {
|
||||
* // do whatever you want.
|
||||
* }
|
||||
* MyModel *model = ...;
|
||||
* CallbackTraceSource<Packet> *source = model->PeekSomethingTraceSource ();
|
||||
* source->AddCallback (MakeCallback (&MySomethingSink));
|
||||
* \endcode
|
||||
*
|
||||
* The full power of the tracing system comes however from its ns3::NodeList::Connect
|
||||
* method which is described in the following sections.
|
||||
*
|
||||
* \section TraceConnection Connecting Trace Sources to Trace Sinks
|
||||
*
|
||||
* If a trace source is integrated in the ns-3 trace connection facility, a user
|
||||
* should call the ns3::NodeList::Connect method to establish a connection between
|
||||
* a trace sink and a set of matching trace sources. The second argument to that
|
||||
* method is a callback to the user's trace sink.
|
||||
* That callback is easy to construct: call ns3::MakeCallback and you are done. The
|
||||
* first argument is a string whose format is similar to a unix path and which is
|
||||
* used to uniquely identify the set of trace sources you want to connect to.
|
||||
* The set of acceptable path strings is also documented in the \ref TraceSourceList.
|
||||
*
|
||||
* So, what does this look like from the perspective of a user ? If we wanted to
|
||||
* connect to a trace source defined somewhere deep into the a set of NetDevice objects
|
||||
* located in some nodes of the system, we could write the following:
|
||||
* \code
|
||||
* void
|
||||
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
|
||||
* {
|
||||
* // for example, print the arguments
|
||||
* std::cout << "packet: " << packet << std::endl;
|
||||
* }
|
||||
* // connect the above sink to a matching trace source
|
||||
* NodeList::Connect ("/nodes/* /devices/* /rx", MakeCallback &DoSomethingTraceSink);
|
||||
* \endcode
|
||||
*
|
||||
* The connection path string "/nodes/* /devices/* /rx" matches the "rx" trace source
|
||||
* located in every netdevice located in every node. The syntax of that path string
|
||||
* is loosely based on regular expressions so, a user could conceivably connect
|
||||
* to the trace sources present in only one node identified by node index:
|
||||
* "/nodex/3/devices/* /rx".
|
||||
*
|
||||
* The matching algorithm used here is very useful since it allows you to connect
|
||||
* at once a large set of trace sources to a single sink but it introduces another
|
||||
* problem: it becomes impossible when you receive an event in your trace sink to
|
||||
* know from _which_ trace source the event is coming from. In our example, the
|
||||
* trace source might be coming from the NetDevice number 2 of Node 10 or Netdevice
|
||||
* number 0 of Node 5. In both cases, you might need to know which of these NetDevice
|
||||
* is generating this event, if only to generate some ascii trace dump. Another
|
||||
* similar use-case is that you might have connected the same trace sink to
|
||||
* multiple types of events which have the same signature: it is quite common
|
||||
* to receive all tx, rx, and drop events in the same trace sink and that would be
|
||||
* quite trivial to achieve with a string such as: "/nodes/* /devices/* /*"
|
||||
*
|
||||
* The source of a trace event can be retrieved from a trace sink using
|
||||
* different means: the simplest
|
||||
* way to get this information is to use the builtin printing facility of
|
||||
* the TraceContext object:
|
||||
* \code
|
||||
* void
|
||||
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
|
||||
* {
|
||||
* // for example, print the arguments
|
||||
* std::cout << "context=\"" << context << "\" packet: " << packet << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
* The above code is going to generate output which looks like the following:
|
||||
* \code
|
||||
* context="nodeid=2 device=0 dev-rx" packet: IPV4(tos 0x0 ttl 64 id 0 offset ...
|
||||
* context="nodeid=1 device=0 dev-rx" packet: IPV4(tos 0x0 ttl 64 id 0 offset ...
|
||||
* ...
|
||||
* \endcode
|
||||
*
|
||||
* Another more advanced way to get information out of a TraceContext is to call its
|
||||
* ns3::TraceContext::GetElement method. This method takes as its first and only
|
||||
* argument an instance of the object we want to read and the list of available
|
||||
* object instances we can read from a TraceContext is documented, once again,
|
||||
* in the \ref TraceSourceList. For example, we could write the following to
|
||||
* generate adhoc trace output:
|
||||
* \code
|
||||
* void DeviceRxSink (const TraceContext &context, const Packet &packet)
|
||||
* {
|
||||
* NodeListIndex nodeIndex;
|
||||
* NodeNetDeviceIndex deviceIndex;
|
||||
* context.GetElement (nodeIndex);
|
||||
* context.GetElement (deviceIndex);
|
||||
* std::cout << "node-index=" << nodeIndex.Get ();
|
||||
* std::cout << ", device-index=" << deviceIndex.Get ();
|
||||
* std::cout << ", packet: " << packet;
|
||||
* std::cout << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \section ExportingTraceSources Exporting new Trace Sources
|
||||
*
|
||||
* Using existing trace sources to connect them to a set of adhoc trace sinks
|
||||
* is not really complicated but, setting up new trace sources which can hook
|
||||
* in this automatic connection system is a bit more complicated.
|
||||
*
|
||||
* So far, we know that a model author can generate trace events really easily:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (Packet packet)
|
||||
* {
|
||||
* // report this event on packet with value
|
||||
* m_doSomething (packet);
|
||||
* // do something
|
||||
* }
|
||||
* private:
|
||||
* // report every "something" function call.
|
||||
* CallbackTraceSource<Packet> m_doSomething;
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* To make these new trace sources available to the rest of the connection system,
|
||||
* the first step is to make sure that your model object derives from the ns3::Object
|
||||
* base class either directly (as shown below) or indirectly through another base class:
|
||||
* \code
|
||||
* class MyModel : public Object {...};
|
||||
* // or:
|
||||
* class SomeOtherObject : public Object {...};
|
||||
* class MyModel : public SomeOtherObject {...};
|
||||
* \endcode
|
||||
*
|
||||
* This is pretty trivial and lays the ground for the second step: overriding the
|
||||
* ns3::Object::GetTraceResolver method:
|
||||
* \code
|
||||
* class MyModel : public MyParent
|
||||
* {
|
||||
* public:
|
||||
* // declare overriden method
|
||||
* virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
* private:
|
||||
* // the new trace source to export.
|
||||
* CallbackTraceSource<Packet> m_rxSource;
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* To implement this method, you could attempt to implement a new subclass of
|
||||
* the ns3::TraceResolver base class and return an instance from this method but
|
||||
* this would be very hard. Instead, you should use the helper class
|
||||
* ns3::CompositeTraceResolver to register your trace sources and chain up to
|
||||
* your parent:
|
||||
* \code
|
||||
* Ptr<TraceResolver>
|
||||
* MyModel::GetTraceResolver (void) const
|
||||
* {
|
||||
* // create an empty trace resolver
|
||||
* Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
* // register m_rxSource
|
||||
* resolver->AddSource ("rx", // the name of the trace source in the path string
|
||||
* TraceDoc ("some help text to explain the purpose of this trace source",
|
||||
* "Packet", // the type of the first argument to the trace source
|
||||
* "the purpose of the first argument",
|
||||
* "type-of-second-argument", "purpose-of-second-argument"),
|
||||
* m_rxSource // the trace source itself is registered
|
||||
* );
|
||||
* // make sure we include the trace sources implemented in the parent.
|
||||
* resolver->SetParentResolver (MyParent::GetTraceResolver ());
|
||||
* return resolver;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Once you have written that code, you must make sure that this new method GetTraceResolver
|
||||
* is going to be called at some point by the tracing system. If your model is located somewhere
|
||||
* deep in MAC or PHY layer, that is, it is part of a NetDevice implementation, all you
|
||||
* have to do is to make sure that your model is registered as a "composite" of your NetDevice
|
||||
* subclass:
|
||||
* \code
|
||||
* class MyNetDevice : public NetDevice
|
||||
* {
|
||||
* public:
|
||||
* Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
* private:
|
||||
* Ptr<MyModel> m_model;
|
||||
* };
|
||||
*
|
||||
* Ptr<TraceResolver>
|
||||
* MyNetDevice::GetTraceResolver (void) const
|
||||
* {
|
||||
* Ptr<CompositeTraceResolver> resolver = ...;
|
||||
* // register other trace source
|
||||
* ...
|
||||
* // register now your model as a "composite"
|
||||
* resolver->AddComposite ("my-model", m_model);
|
||||
* // chain up to parent.
|
||||
* resolver->SetParentResolver (NetDevice::GetTraceResolver ());
|
||||
* return resolver;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* The code above will make your "rx" trace source appear under the
|
||||
* /nodes/xx/devices/xx/my-model/rx namespace path.
|
||||
*
|
||||
* If you have implemented a new layer 3 or 4 protocol object, the process to
|
||||
* export your trace sources is quite similar. You need to subclass from
|
||||
* ns3::Object, override the ns3::Object::GetTraceResolver method, make
|
||||
* sure you chain up to your parent's GetTraceResolver method, and, finally,
|
||||
* make sure that someone calls your new GetTraceResolver method. How to accomplish
|
||||
* the latter should be documented in the node's API documentation which describes
|
||||
* how to implement a new layer 3 or 4 protocol object.
|
||||
*
|
||||
* \section AdvancedTraceContext Creating new Trace Context Elements
|
||||
*
|
||||
* The last important feature which model developers need to understand
|
||||
* is how to provide extra context information to trace sinks. For example,
|
||||
* if your model exports both rx and tx trace sources which share the same
|
||||
* signature, it is quite natural for a user to connect to a single trace sink
|
||||
* to both of them with a trace path string such as "/nodes/* /devices/* /(rx|tx)".
|
||||
* In this case, it becomes necessary to be able, from the trace sink function,
|
||||
* to tell which event triggered the call to the trace sink: a rx or a tx event.
|
||||
*
|
||||
* That example is detailed below with a TX, a RX, and a DROP source:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* private:
|
||||
* CallbackTraceSource<Packet> m_rxSource;
|
||||
* CallbackTraceSource<Packet> m_txSource;
|
||||
* CallbackTraceSource<Packet> m_dropSource;
|
||||
* };
|
||||
* \endcode
|
||||
* When a single sink is connected to all 3 sources here, one might want
|
||||
* to write code like the following:
|
||||
* \code
|
||||
* void DeviceRxSink (const TraceContext &context, const Packet &packet)
|
||||
* {
|
||||
* switch (type) {
|
||||
* case RX:
|
||||
* std::cout << "rx" << std::endl;
|
||||
* break;
|
||||
* case TX:
|
||||
* std::cout << "tx" << std::endl;
|
||||
* break;
|
||||
* case DROP:
|
||||
* std::cout << "drop" << std::endl;
|
||||
* break;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \subsection AdvancedTraceContextSimpleSolution The simple solution
|
||||
*
|
||||
* The simplest way to do achieve the result shown above is to include
|
||||
* in the trace source an extra explicit argument which describes the source event:
|
||||
* - define a small enum with 3 values
|
||||
* - change the signature of m_rxSource, m_txSource, and m_dropSource to include
|
||||
* the enum
|
||||
* - pass the enum value in each event
|
||||
*
|
||||
* The resulting code is shown below:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* // define the trace type enum.
|
||||
* enum TraceType {
|
||||
* RX,
|
||||
* TX,
|
||||
* DROP
|
||||
* };
|
||||
* private:
|
||||
* // generate events
|
||||
* void NotifyRxPacket (Packet p) {
|
||||
* m_rxSource (p, MyModel::RX);
|
||||
* }
|
||||
* void NotifyTxPacket (Packet p) {
|
||||
* m_rxSource (p, MyModel::TX);
|
||||
* }
|
||||
* void NotifyDropPacket (Packet p) {
|
||||
* m_rxSource (p, MyModel::DROP);
|
||||
* }
|
||||
* CallbackTraceSource<Packet,enum TraceType> m_rxSource;
|
||||
* CallbackTraceSource<Packet,enum TraceType> m_txSource;
|
||||
* CallbackTraceSource<Packet,enum TraceType> m_dropSource;
|
||||
* };
|
||||
* \endcode
|
||||
* These 3 new sources can be connected easily to a new trace sink:
|
||||
* \code
|
||||
* void ASimpleTraceSink (const TraceContext &context, const Packet &packet, enum MyModel::TraceType type)
|
||||
* {
|
||||
* // here, read the "type" argument
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* This solution works but it makes it impossible to connect a single trace sink to a set
|
||||
* of trace sources which represent "rx" events in different NetDevice objects since
|
||||
* each of them will define a different enum type with different values: since the
|
||||
* trace sink signature must match exactly the trace source signature, it is impossible
|
||||
* to connect at the same time to all "rx" events of different NetDevice.
|
||||
*
|
||||
* \subsection AdvancedTraceContextFancySolution The more complex and generic solution
|
||||
*
|
||||
* There is, hopefully, a way to get the best of both worlds, that is, to allow a
|
||||
* user to connect to a lot of trace source events of the same kind but coming from different
|
||||
* implementations and to allow the user to differentiate between these different
|
||||
* implementations.
|
||||
*
|
||||
* Rather than define an adhoc enum type with a list of trace sources, you can also
|
||||
* define a new ns3::TraceContextElement for your source sources. For example, if you
|
||||
* define a new MyModelTraceType class which contains the type of trace, your users can
|
||||
* then write trace sink code which looks like this:
|
||||
* \code
|
||||
* void AFancyTraceSink (const TraceContext &context, const Packet &packet)
|
||||
* {
|
||||
* MyModelTraceType type;
|
||||
* if (context.GetElement (type))
|
||||
* {
|
||||
* switch (type.Get ())
|
||||
* {
|
||||
* case MyModelTraceType::RX:
|
||||
* std::cout << "rx" << std::endl;
|
||||
* break;
|
||||
* case MyModelTraceType::TX:
|
||||
* std::cout << "tx" << std::endl;
|
||||
* break;
|
||||
* case MyModelTraceType::DROP:
|
||||
* std::cout << "drop" << std::endl;
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Of course, since the type of trace is stored in the TraceContext, your users can
|
||||
* also take the shortcut which uses the printing functionality of the TraceContext:
|
||||
* \code
|
||||
* void ALessFancyTraceSink (const TraceContext &context, const Packet &packet)
|
||||
* {
|
||||
* std::cout << "context=\"" << context << "\" packet: " << packet << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
* which will generate something like the following when the trace source comes
|
||||
* from MyModel:
|
||||
* \code
|
||||
* context="my-model-rx" packet: ...
|
||||
* \endcode
|
||||
*
|
||||
* The first step to achieve this is to define and implement a new
|
||||
* subclass of the ns3::TraceContextElement base class. The exact list of
|
||||
* public methods which must be implemented is described in the API
|
||||
* documentation of the ns3::TraceContextElement class.
|
||||
* \code
|
||||
* class MyModelTraceType : public TraceContextElement
|
||||
* {
|
||||
* public:
|
||||
* enum Type {
|
||||
* RX,
|
||||
* TX,
|
||||
* DROP
|
||||
* };
|
||||
* // called from MyModel::GetTraceResolver
|
||||
* MyModelTraceType (enum Type type);
|
||||
* // called from trace sink
|
||||
* enum Type Get (void) const;
|
||||
* // needed by the tracing subsystem
|
||||
* static uint16_t GetUid (void);
|
||||
* // needed by the tracing subsystem to
|
||||
* // print the content of a TraceContext
|
||||
* void Print (std::ostream &os) const;
|
||||
* // needed by the tracing subsystem to
|
||||
* // generate the doxygen documentation.
|
||||
* std::string GetTypeName (void) const;
|
||||
* private:
|
||||
* enum Type m_type;
|
||||
* };
|
||||
* \endcode
|
||||
* The implementation does not require much thinking:
|
||||
* \code
|
||||
* MyModelTraceType::MyModelTraceType (enum Type type)
|
||||
* : m_type (type)
|
||||
* {}
|
||||
* enum Type
|
||||
* MyModelTraceType::Get (void) const
|
||||
* {
|
||||
* return m_type;
|
||||
* }
|
||||
* uint16_t
|
||||
* MyModelTraceType::GetUid (void)
|
||||
* {
|
||||
* // use protected TraceContextElement::AllocateUid method
|
||||
* // the input string is used to uniquely identify this new subclass
|
||||
* static uint16_t uid = AllocateUid<MyModelTraceType> ("ns3::MyModelTraceType");
|
||||
* return uid;
|
||||
* }
|
||||
* void
|
||||
* MyModelTraceType::Print (std::ostream &os) const
|
||||
* (
|
||||
* // this method is invoked by the print function of a TraceContext
|
||||
* // if it contains an instance of this TraceContextElement.
|
||||
* switch (m_type) {
|
||||
* case RX: os << "rx"; break;
|
||||
* // ...
|
||||
* }
|
||||
* )
|
||||
* std::string
|
||||
* MyModelTraceType::GetTypeName (void) const
|
||||
* {
|
||||
* // This method should return a fully-qualified c++ typename
|
||||
* // This method is used only for documentation purposes to
|
||||
* // generate the content of the Trace Source List.
|
||||
* return "ns3::MyModelTraceType";
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Once this subclass is implemented, the work is almost completed: you
|
||||
* just need to pass an instance of that class as the last argument of
|
||||
* the ns3::CompositeTraceResolver::AddSource method as shown below:
|
||||
* \code
|
||||
* Ptr<TraceResolver>
|
||||
* MyModel::GetTraceResolver (void) const
|
||||
* {
|
||||
* // create an empty trace resolver
|
||||
* Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
* // register m_rxSource
|
||||
* resolver->AddSource ("rx", // the name of the trace source in the path string
|
||||
* TraceDoc ("some help text to explain the purpose of this trace source",
|
||||
* "Packet", // the type of the first argument to the trace source
|
||||
* "the purpose of the first argument",
|
||||
* "type-of-second-argument", "purpose-of-second-argument"),
|
||||
* m_rxSource, // the trace source itself is registered
|
||||
* // the TraceContextElement associated to this trace source.
|
||||
* MyModelTraceType (MyModelTraceType::RX)
|
||||
* );
|
||||
* // make sure we include the trace sources implemented in the parent.
|
||||
* resolver->SetParentResolver (MyParent::GetTraceResolver ());
|
||||
* return resolver;
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
@@ -15,7 +15,7 @@
|
||||
using namespace ns3;
|
||||
|
||||
static void
|
||||
CourseChange (Ptr<const MobilityModel> position)
|
||||
CourseChange (const TraceContext &context, Ptr<const MobilityModel> position)
|
||||
{
|
||||
Position pos = position->Get ();
|
||||
std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
|
||||
@@ -39,7 +39,7 @@ int main (int argc, char *argv[])
|
||||
for (uint32_t i = 0; i < 10000; i++)
|
||||
{
|
||||
Ptr<MobilityModelNotifier> notifier = Create<MobilityModelNotifier> ();
|
||||
notifier->RegisterListener (MakeCallback (&CourseChange));
|
||||
notifier->TraceConnect ("/course-change", MakeCallback (&CourseChange));
|
||||
objects.push_back (notifier);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef ARRAY_TRACE_RESOLVER_H
|
||||
#define ARRAY_TRACE_RESOLVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "ns3/callback.h"
|
||||
#include "trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief a helper class to offer trace resolution for an array of objects.
|
||||
* \ingroup lowleveltracing
|
||||
*/
|
||||
template <typename T, typename INDEX>
|
||||
class ArrayTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \param context trace context associated to this trace resolver
|
||||
* \param getSize callback which returns dynamically the size of underlying array
|
||||
* \param get callback which returns any element in the underlying array
|
||||
*
|
||||
* Construct a trace resolver which can match any input integer
|
||||
* against an element in an array. The array is accessed using a
|
||||
* pair of callbacks. It is the responsability of the user to
|
||||
* provide two such callbacks whose job is to adapt the array
|
||||
* API to the resolver needs. Each element of the array is expected
|
||||
* to provide a method named CreateTraceResolver which takes as
|
||||
* only argument a reference to a const TraceContext and returns
|
||||
* a pointer to a TraceResolver. i.e. the signature is:
|
||||
* TraceResolver * (*) (TraceContext const &)
|
||||
*/
|
||||
ArrayTraceResolver (TraceContext const &context,
|
||||
Callback<uint32_t> getSize,
|
||||
Callback<T, uint32_t> get);
|
||||
private:
|
||||
virtual TraceResolverList DoLookup (std::string id) const;
|
||||
Callback<uint32_t> m_getSize;
|
||||
Callback<T, uint32_t> m_get;
|
||||
};
|
||||
}//namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
template <typename T, typename INDEX>
|
||||
ArrayTraceResolver<T,INDEX>::ArrayTraceResolver (TraceContext const &context,
|
||||
Callback<uint32_t> getSize,
|
||||
Callback<T, uint32_t> get)
|
||||
: TraceResolver (context),
|
||||
m_getSize (getSize),
|
||||
m_get (get)
|
||||
{}
|
||||
template <typename T, typename INDEX>
|
||||
TraceResolver::TraceResolverList
|
||||
ArrayTraceResolver<T,INDEX>::DoLookup (std::string id) const
|
||||
{
|
||||
TraceResolverList list;
|
||||
if (id == "*")
|
||||
{
|
||||
for (uint32_t i = 0; i < m_getSize (); i++)
|
||||
{
|
||||
TraceContext context = GetContext ();
|
||||
INDEX index = i;
|
||||
context.Add (index);
|
||||
list.push_back (m_get (i)->CreateTraceResolver (context));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* ARRAY_TRACE_RESOLVER_H */
|
||||
@@ -1,157 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006,2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef CALLBACK_TRACE_H
|
||||
#define CALLBACK_TRACE_H
|
||||
|
||||
#include <list>
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/fatal-error.h"
|
||||
#include "trace-context.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
/**
|
||||
* \brief log arbitrary number of parameters to a matching ns3::Callback
|
||||
* \ingroup lowleveltracing
|
||||
*
|
||||
* Whenever operator () is invoked on this class, the call and its arguments
|
||||
* are forwarded to the internal matching ns3::Callback.
|
||||
*/
|
||||
template<typename T1 = empty, typename T2 = empty,
|
||||
typename T3 = empty, typename T4 = empty>
|
||||
class CallbackTraceSource {
|
||||
public:
|
||||
CallbackTraceSource ();
|
||||
void AddCallback (CallbackBase const & callback, TraceContext const & context);
|
||||
void RemoveCallback (CallbackBase const & callback);
|
||||
void operator() (void);
|
||||
void operator() (T1 a1);
|
||||
void operator() (T1 a1, T2 a2);
|
||||
void operator() (T1 a1, T2 a2, T3 a3);
|
||||
void operator() (T1 a1, T2 a2, T3 a3, T4 a4);
|
||||
|
||||
private:
|
||||
typedef std::list<Callback<void,TraceContext const &,T1,T2,T3,T4> > CallbackList;
|
||||
TraceContext m_context;
|
||||
CallbackList m_callbackList;
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
// implementation below.
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
CallbackTraceSource<T1,T2,T3,T4>::CallbackTraceSource ()
|
||||
: m_callbackList ()
|
||||
{}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::AddCallback (CallbackBase const & callback,
|
||||
TraceContext const &context)
|
||||
{
|
||||
Callback<void,TraceContext const &,T1,T2,T3,T4> cb;
|
||||
cb.Assign (callback);
|
||||
m_context.Add (context);
|
||||
m_callbackList.push_back (cb);
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::RemoveCallback (CallbackBase const & callback)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); /* empty */)
|
||||
{
|
||||
if ((*i).IsEqual (callback))
|
||||
{
|
||||
i = m_callbackList.erase (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (void)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1, a2);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1, a2, a3);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1, a2, a3, a4);
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* CALLBACK_TRACE_H */
|
||||
@@ -1,375 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "composite-trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context)
|
||||
: TraceResolver (context)
|
||||
{}
|
||||
|
||||
CompositeTraceResolver::~CompositeTraceResolver ()
|
||||
{}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver)
|
||||
{
|
||||
TraceContext traceContext = GetContext ();
|
||||
DoAdd (name, createResolver, traceContext);
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::DoAdd (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver,
|
||||
TraceContext const &context)
|
||||
{
|
||||
struct CallbackTraceSourceItem item;
|
||||
item.name = name;
|
||||
item.createResolver = createResolver;
|
||||
item.context = context;
|
||||
m_items.push_back (item);
|
||||
}
|
||||
|
||||
TraceResolver::TraceResolverList
|
||||
CompositeTraceResolver::DoLookup (std::string id) const
|
||||
{
|
||||
if (id == "*")
|
||||
{
|
||||
TraceResolver::TraceResolverList list;
|
||||
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
|
||||
{
|
||||
list.push_back (i->createResolver (i->context));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
std::string::size_type start, end;
|
||||
start = id.find_first_of ("(", 0);
|
||||
end = id.find_first_of (")", 0);
|
||||
if (start != 0 || end != (id.size ()-1))
|
||||
{
|
||||
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
|
||||
{
|
||||
if (i->name == id)
|
||||
{
|
||||
TraceResolver::TraceResolverList list;
|
||||
list.push_back (i->createResolver (i->context));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::list<std::string> names;
|
||||
std::string alternatives = std::string (id, start+1, end-1);
|
||||
std::string::size_type next, cur;
|
||||
next = 0;
|
||||
cur = 0;
|
||||
while (true)
|
||||
{
|
||||
std::string element;
|
||||
next = alternatives.find ("|", cur);
|
||||
if (next == std::string::npos)
|
||||
{
|
||||
element = std::string (alternatives, cur, alternatives.size ());
|
||||
names.push_back (element);
|
||||
break;
|
||||
}
|
||||
element = std::string (alternatives, cur, next);
|
||||
names.push_back (element);
|
||||
cur = next + 1;
|
||||
}
|
||||
TraceResolver::TraceResolverList list;
|
||||
for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++)
|
||||
{
|
||||
for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++)
|
||||
{
|
||||
if (j->name == *i)
|
||||
{
|
||||
list.push_back (j->createResolver (j->context));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "trace-context-element.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TraceSourceTest : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
enum Sources {
|
||||
DOUBLEA,
|
||||
DOUBLEB,
|
||||
SUBRESOLVER,
|
||||
};
|
||||
static uint16_t GetUid (void)
|
||||
{static uint16_t uid = AllocateUid<TraceSourceTest> ("TraceSourceTest"); return uid;}
|
||||
void Print (std::ostream &os)
|
||||
{os << "tracesource=";
|
||||
if (m_sources == DOUBLEA) {os << "doubleA";}
|
||||
else if (m_sources == DOUBLEB) {os << "doubleB";}
|
||||
else if (m_sources == SUBRESOLVER) {os << "subresolver";}
|
||||
}
|
||||
TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {}
|
||||
TraceSourceTest (enum Sources sources) :m_sources (sources) {}
|
||||
bool IsDoubleA (void) {return m_sources == TraceSourceTest::DOUBLEA;}
|
||||
bool IsDoubleB (void) {return m_sources == TraceSourceTest::DOUBLEB;}
|
||||
private:
|
||||
enum TraceSourceTest::Sources m_sources;
|
||||
};
|
||||
|
||||
class SubTraceSourceTest : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
enum Sources {
|
||||
INT,
|
||||
};
|
||||
static uint16_t GetUid (void)
|
||||
{static uint16_t uid = AllocateUid<SubTraceSourceTest> ("SubTraceSourceTest"); return uid;}
|
||||
void Print (std::ostream &os)
|
||||
{os << "subtracesource=int";}
|
||||
SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {}
|
||||
SubTraceSourceTest (enum Sources sources) : m_sources (sources) {}
|
||||
private:
|
||||
enum Sources m_sources;
|
||||
};
|
||||
|
||||
class CompositeTraceResolverTest : public Test
|
||||
{
|
||||
public:
|
||||
CompositeTraceResolverTest ();
|
||||
virtual ~CompositeTraceResolverTest ();
|
||||
virtual bool RunTests (void);
|
||||
private:
|
||||
void TraceDouble (TraceContext const &context, double v);
|
||||
void TraceInt (TraceContext const &context, int v);
|
||||
TraceResolver *CreateSubResolver (TraceContext const &context);
|
||||
|
||||
|
||||
bool m_gotDoubleA;
|
||||
bool m_gotDoubleB;
|
||||
CallbackTraceSource<int> m_traceInt;
|
||||
bool m_gotInt;
|
||||
};
|
||||
|
||||
CompositeTraceResolverTest::CompositeTraceResolverTest ()
|
||||
: Test ("CompositeTraceResolver")
|
||||
{}
|
||||
CompositeTraceResolverTest::~CompositeTraceResolverTest ()
|
||||
{}
|
||||
void
|
||||
CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
|
||||
{
|
||||
TraceSourceTest source;
|
||||
context.Get (source);
|
||||
if (source.IsDoubleA ())
|
||||
{
|
||||
m_gotDoubleA = true;
|
||||
}
|
||||
else if (source.IsDoubleB ())
|
||||
{
|
||||
m_gotDoubleB = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("should not get any other trace source in this sink");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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,
|
||||
SubTraceSourceTest (SubTraceSourceTest::INT));
|
||||
return subresolver;
|
||||
}
|
||||
bool
|
||||
CompositeTraceResolverTest::RunTests (void)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
CallbackTraceSource<double> traceDoubleA;
|
||||
CallbackTraceSource<double> traceDoubleB;
|
||||
TraceContext context;
|
||||
|
||||
CompositeTraceResolver resolver (context) ;
|
||||
|
||||
resolver.Add ("trace-double-a", traceDoubleA,
|
||||
TraceSourceTest (TraceSourceTest::DOUBLEA));
|
||||
resolver.Add ("trace-double-b", traceDoubleB,
|
||||
TraceSourceTest (TraceSourceTest::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),
|
||||
TraceSourceTest (TraceSourceTest::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 */
|
||||
@@ -1,222 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef COMPOSITE_TRACE_RESOLVER_H
|
||||
#define COMPOSITE_TRACE_RESOLVER_H
|
||||
|
||||
#include "ns3/callback.h"
|
||||
#include "trace-resolver.h"
|
||||
#include "callback-trace-source.h"
|
||||
#include "uv-trace-source.h"
|
||||
#include "sv-trace-source.h"
|
||||
#include "fv-trace-source.h"
|
||||
#include "terminal-trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief a helper class to aggregate contained TraceResolver and other trace sources.
|
||||
* \ingroup lowleveltracing
|
||||
*/
|
||||
class CompositeTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
CompositeTraceResolver (TraceContext const &context);
|
||||
virtual ~CompositeTraceResolver ();
|
||||
/**
|
||||
* \param name name of trace source
|
||||
* \param trace a callback trace source
|
||||
* \param context the context associated to this trace source
|
||||
*
|
||||
* Add a callback trace source in this resolver. This trace
|
||||
* source will match the name specified during namespace
|
||||
* resolution. The TraceContext of this trace source will also
|
||||
* be automatically extended to contain the input context.
|
||||
*/
|
||||
template <typename T1, typename T2,
|
||||
typename T3, typename T4,
|
||||
typename T>
|
||||
void Add (std::string name,
|
||||
CallbackTraceSource<T1,T2,T3,T4> &trace, T const &context);
|
||||
/**
|
||||
* \param name name of trace source
|
||||
* \param trace a signed variable trace source
|
||||
* \param context the context associated to this trace source
|
||||
*
|
||||
* Add a signed variable trace source in this resolver.
|
||||
* This trace source will match the name specified during namespace
|
||||
* resolution. The TraceContext of this trace source will also
|
||||
* be automatically extended to contain the input context.
|
||||
*/
|
||||
template <typename T>
|
||||
void Add (std::string name,
|
||||
SVTraceSource<T> &trace, T const &context);
|
||||
/**
|
||||
* \param name name of trace source
|
||||
* \param trace an unsigned variable trace source
|
||||
* \param context the context associated to this trace source
|
||||
*
|
||||
* Add an unsigned variable trace source in this resolver.
|
||||
* This trace source will match the name specified during namespace
|
||||
* resolution. The TraceContext of this trace source will also
|
||||
* be automatically extended to contain the input context.
|
||||
*/
|
||||
template <typename T>
|
||||
void Add (std::string name,
|
||||
UVTraceSource<T> &trace, T const &context);
|
||||
/**
|
||||
* \param name name of trace source
|
||||
* \param trace a floating-point variable trace source
|
||||
* \param context the context associated to this trace source
|
||||
*
|
||||
* Add a floating-point variable trace source in this resolver.
|
||||
* This trace source will match the name specified during namespace
|
||||
* resolution. The TraceContext of this trace source will also
|
||||
* be automatically extended to contain the input context.
|
||||
*/
|
||||
template <typename T>
|
||||
void Add (std::string name,
|
||||
FVTraceSource<T> &trace, T const &context);
|
||||
|
||||
/**
|
||||
* \param name name of child trace resolver
|
||||
* \param createResolver a trace resolver constructor
|
||||
* \param context the context associated to this entry
|
||||
*
|
||||
* Add a child trace resolver to this resolver. This child
|
||||
* trace resolver will match the name specified during
|
||||
* namespace resolution. When this happens, the constructor
|
||||
* will be invoked to create the child trace resolver and
|
||||
* the associated TraceContext will be automatically extended
|
||||
* to contain the input context.
|
||||
*/
|
||||
template <typename T>
|
||||
void Add (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver,
|
||||
T const &context);
|
||||
|
||||
/**
|
||||
* \param name name of child trace resolver
|
||||
* \param createResolver a trace resolver constructor
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
void Add (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver);
|
||||
private:
|
||||
template <typename SOURCE, typename CONTEXT>
|
||||
void DoAddTraceSource (std::string name,
|
||||
SOURCE &traceSource, CONTEXT const &context);
|
||||
template <typename SOURCE>
|
||||
static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace,
|
||||
TraceContext const &context);
|
||||
void DoAdd (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver,
|
||||
TraceContext const &context);
|
||||
virtual TraceResolverList DoLookup (std::string id) const;
|
||||
|
||||
struct CallbackTraceSourceItem
|
||||
{
|
||||
std::string name;
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver;
|
||||
TraceContext context;
|
||||
};
|
||||
|
||||
typedef std::list<struct CallbackTraceSourceItem> TraceItems;
|
||||
TraceItems m_items;
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
template <typename SOURCE, typename CONTEXT>
|
||||
void
|
||||
CompositeTraceResolver::DoAddTraceSource (std::string name,
|
||||
SOURCE &traceSource, CONTEXT const &context)
|
||||
{
|
||||
TraceContext traceContext = GetContext ();
|
||||
traceContext.Add (context);
|
||||
TraceResolver *(*create) (SOURCE *trace, TraceContext const &context);
|
||||
create = &CompositeTraceResolver::CreateTerminalTraceResolver<SOURCE>;
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver =
|
||||
MakeBoundCallback (create, &traceSource);
|
||||
DoAdd (name, createResolver, traceContext);
|
||||
}
|
||||
|
||||
template <typename SOURCE>
|
||||
TraceResolver *
|
||||
CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource,
|
||||
TraceContext const &context)
|
||||
{
|
||||
return new TerminalTraceResolver<SOURCE> (*traceSource, context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T1, typename T2,
|
||||
typename T3, typename T4,
|
||||
typename T>
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
CallbackTraceSource<T1,T2,T3,T4> &trace,
|
||||
T const &context)
|
||||
{
|
||||
DoAddTraceSource (name, trace, context);
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
SVTraceSource<T> &trace, T const &context)
|
||||
{
|
||||
DoAddTraceSource (name, trace, context);
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
UVTraceSource<T> &trace, T const &context)
|
||||
{
|
||||
DoAddTraceSource (name, trace, context);
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
FVTraceSource<T> &trace, T const &context)
|
||||
{
|
||||
DoAddTraceSource (name, trace, context);
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver,
|
||||
T const &context)
|
||||
{
|
||||
TraceContext traceContext = GetContext ();
|
||||
traceContext.Add (context);
|
||||
DoAdd (name, createResolver, traceContext);
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* COMPOSITE_TRACE_RESOLVER_H */
|
||||
@@ -1,52 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef EMPTY_TRACE_RESOLVER_H
|
||||
#define EMPTY_TRACE_RESOLVER_H
|
||||
|
||||
#include "trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TraceContext;
|
||||
|
||||
/**
|
||||
* \brief a TraceResolver instance which does not resolve anything.
|
||||
* \ingroup tracing
|
||||
*
|
||||
* Trying to resolve against this class will yield no matches and no
|
||||
* connections. Returning an instance of this class from a
|
||||
* CreateTraceResolver method is a hand way of not implementing
|
||||
* any Tracing code.
|
||||
*/
|
||||
class EmptyTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \param o necessary context for this class.
|
||||
*
|
||||
* The only constructor exported by this class.
|
||||
*/
|
||||
EmptyTraceResolver (TraceContext const &o);
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* EMPTY_TRACE_RESOLVER_H */
|
||||
@@ -199,6 +199,12 @@ Packet::Deserialize (Buffer buffer)
|
||||
buffer.RemoveAtStart (metadataDeserialized);
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const Packet &packet)
|
||||
{
|
||||
packet.Print (os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
@@ -328,6 +328,8 @@ private:
|
||||
static uint32_t m_globalUid;
|
||||
};
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const Packet &packet);
|
||||
|
||||
/**
|
||||
* \defgroup packetperf Packet Performance
|
||||
* The current implementation of the byte buffers and tag list is based
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef TERMINAL_TRACE_RESOLVER_H
|
||||
#define TERMINAL_TRACE_RESOLVER_H
|
||||
|
||||
#include "trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TraceContext;
|
||||
|
||||
template <typename T>
|
||||
class TerminalTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
TerminalTraceResolver (T &traceSource, TraceContext const &context);
|
||||
private:
|
||||
virtual void DoConnect (CallbackBase const &cb);
|
||||
virtual void DoDisconnect (CallbackBase const &cb);
|
||||
T &m_traceSource;
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
template <typename T>
|
||||
TerminalTraceResolver<T>::TerminalTraceResolver (T &traceSource,
|
||||
TraceContext const &context)
|
||||
: TraceResolver (context),
|
||||
m_traceSource (traceSource)
|
||||
{}
|
||||
template <typename T>
|
||||
void
|
||||
TerminalTraceResolver<T>::DoConnect (CallbackBase const &cb)
|
||||
{
|
||||
m_traceSource.AddCallback (cb, GetContext ());
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
TerminalTraceResolver<T>::DoDisconnect (CallbackBase const &cb)
|
||||
{
|
||||
m_traceSource.RemoveCallback (cb);
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* TERMINAL_TRACE_RESOLVER_H */
|
||||
@@ -1,104 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
TraceResolver::TraceResolver (TraceContext const &context)
|
||||
: m_context (context)
|
||||
{}
|
||||
|
||||
TraceResolver::~TraceResolver ()
|
||||
{}
|
||||
|
||||
TraceContext const &
|
||||
TraceResolver::GetContext (void) const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
void
|
||||
TraceResolver::Connect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
std::string::size_type cur = 1;
|
||||
// check that first char is "/"
|
||||
std::string::size_type next = path.find ("/", cur);
|
||||
std::string element = std::string (path, cur, next-1);
|
||||
TraceResolverList resolverList = DoLookup (element);
|
||||
for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
|
||||
{
|
||||
TraceResolver *resolver = *i;
|
||||
if (next == std::string::npos)
|
||||
{
|
||||
// we really break the recursion here.
|
||||
resolver->DoConnect (cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string subpath = std::string (path, next, std::string::npos);
|
||||
resolver->Connect (subpath, cb);
|
||||
}
|
||||
delete resolver;
|
||||
}
|
||||
resolverList.erase (resolverList.begin (), resolverList.end ());
|
||||
}
|
||||
|
||||
void
|
||||
TraceResolver::Disconnect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
std::string::size_type cur = 1;
|
||||
// check that first char is "/"
|
||||
std::string::size_type next = path.find ("/", cur);
|
||||
std::string element = std::string (path, cur, next-1);
|
||||
TraceResolverList resolverList = DoLookup (element);
|
||||
for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
|
||||
{
|
||||
TraceResolver *resolver = *i;
|
||||
if (next == std::string::npos)
|
||||
{
|
||||
// we really break the recursion here.
|
||||
resolver->DoDisconnect (cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string subpath = std::string (path, next, std::string::npos);
|
||||
resolver->Disconnect (subpath, cb);
|
||||
}
|
||||
delete resolver;
|
||||
}
|
||||
resolverList.erase (resolverList.begin (), resolverList.end ());
|
||||
}
|
||||
|
||||
TraceResolver::TraceResolverList
|
||||
TraceResolver::DoLookup (std::string id) const
|
||||
{
|
||||
return TraceResolverList ();
|
||||
}
|
||||
void
|
||||
TraceResolver::DoConnect (CallbackBase const &cb)
|
||||
{}
|
||||
|
||||
void
|
||||
TraceResolver::DoDisconnect (CallbackBase const &cb)
|
||||
{}
|
||||
|
||||
|
||||
}//namespace ns3
|
||||
@@ -1,119 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef TRACE_RESOLVER_H
|
||||
#define TRACE_RESOLVER_H
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include "trace-context.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class CallbackBase;
|
||||
|
||||
/**
|
||||
* \brief the base class which is used to incremental perform trace
|
||||
* namespace resolution.
|
||||
* \ingroup lowleveltracing
|
||||
*
|
||||
* This class provides a public API to the ns3::TraceRoot object:
|
||||
* - ns3::TraceResolver::Connect
|
||||
* - ns3::TraceResolver::Disconnect
|
||||
*
|
||||
* It also provides an API for its subclasses. Each subclass should
|
||||
* implement one of:
|
||||
* - ns3::TraceResolver::DoLookup
|
||||
* - ns3::TraceResolver::DoConnect and ns3::TraceResolver::DoDisconnect
|
||||
* Each subclass must also provide an ns3::TraceContext to the TraceResolver
|
||||
* constructor. Finally, each subclass can access the ns3::TraceContext
|
||||
* associated to this ns3::TraceResolver through the
|
||||
* ns3::TraceResolver::GetContext method.
|
||||
*/
|
||||
class TraceResolver
|
||||
{
|
||||
public:
|
||||
virtual ~TraceResolver ();
|
||||
/**
|
||||
* \param path the namespace path to resolver
|
||||
* \param cb the callback to connect to the matching namespace
|
||||
*
|
||||
* This method is typically invoked by ns3::TraceRoot but advanced
|
||||
* users could also conceivably call it directly if they want to
|
||||
* skip the ns3::TraceRoot.
|
||||
*/
|
||||
void Connect (std::string path, CallbackBase const &cb);
|
||||
/**
|
||||
* \param path the namespace path to resolver
|
||||
* \param cb the callback to disconnect in the matching namespace
|
||||
*
|
||||
* This method is typically invoked by ns3::TraceRoot but advanced
|
||||
* users could also conceivably call it directly if they want to
|
||||
* skip the ns3::TraceRoot.
|
||||
*/
|
||||
void Disconnect (std::string path, CallbackBase const &cb);
|
||||
protected:
|
||||
/**
|
||||
* \param context the context used to initialize this TraceResolver.
|
||||
*
|
||||
* Every subclass must call this constructor
|
||||
*/
|
||||
TraceResolver (TraceContext const &context);
|
||||
/**
|
||||
* \returns the ns3::TraceContext stored in this ns3::TraceResolver.
|
||||
*
|
||||
* Subclasses usually invoke this method to get access to the
|
||||
* TraceContext stored here to pass it down to the TraceResolver
|
||||
* constructors invoked from within the DoLookup method.
|
||||
*/
|
||||
TraceContext const &GetContext (void) const;
|
||||
typedef std::list<TraceResolver *> TraceResolverList;
|
||||
private:
|
||||
TraceResolver ();
|
||||
/**
|
||||
* \param id the id to resolve. This is supposed to be
|
||||
* one element of the global tracing namespace.
|
||||
* \returns a list of reslvers which match the input namespace element
|
||||
*
|
||||
* A subclass which overrides this method should return a potentially
|
||||
* empty list of pointers to ns3::TraceResolver instances which match
|
||||
* the input namespace element. Each of these TraceResolver should be
|
||||
* instanciated with a TraceContext which holds enough context
|
||||
* information to identify the type of the TraceResolver.
|
||||
*/
|
||||
virtual TraceResolverList DoLookup (std::string id) const;
|
||||
/**
|
||||
* \param cb callback to connect
|
||||
*
|
||||
* This method is invoked on leaf trace resolvers.
|
||||
*/
|
||||
virtual void DoConnect (CallbackBase const &cb);
|
||||
/**
|
||||
* \param cb callback to disconnect
|
||||
*
|
||||
* This method is invoked on leaf trace resolvers.
|
||||
*/
|
||||
virtual void DoDisconnect (CallbackBase const &cb);
|
||||
TraceContext m_context;
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* TRACE_RESOLVER_H */
|
||||
@@ -1,54 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "trace-root.h"
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "ns3/trace-context.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
void
|
||||
TraceRoot::Connect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
TraceResolver *resolver = GetComposite ();
|
||||
resolver->Connect (path, cb);
|
||||
}
|
||||
void
|
||||
TraceRoot::Disconnect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
TraceResolver *resolver = GetComposite ();
|
||||
resolver->Disconnect (path, cb);
|
||||
}
|
||||
void
|
||||
TraceRoot::Register (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver)
|
||||
{
|
||||
CompositeTraceResolver *resolver = GetComposite ();
|
||||
resolver->Add (name, createResolver);
|
||||
}
|
||||
|
||||
CompositeTraceResolver *
|
||||
TraceRoot::GetComposite (void)
|
||||
{
|
||||
static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ());
|
||||
return &resolver;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -1,335 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef TRACE_ROOT_H
|
||||
#define TRACE_ROOT_H
|
||||
|
||||
#include <string>
|
||||
#include "ns3/callback.h"
|
||||
|
||||
/**
|
||||
* \defgroup lowleveltracing Low-level tracing
|
||||
*
|
||||
* This low-level API is built around a few 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 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.
|
||||
*
|
||||
* For example, to define a trace source which notifies you of a new packet
|
||||
* being transmitted, you would have to:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void Tx (Packet const &p);
|
||||
* private:
|
||||
* CallbackTraceSource<Packet const &> m_txTrace;
|
||||
* };
|
||||
*
|
||||
* void
|
||||
* MyModel::Tx (Packet const &p)
|
||||
* {
|
||||
* // trace packet tx event.
|
||||
* m_txTrace (p);
|
||||
* // ... send the packet for real.
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* 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 make these trace sources available to users
|
||||
* to allow them to connect any number of trace sources to any number
|
||||
* of user trace sinks. While it would be possible to make each model
|
||||
* export directly each of his trace source instances and request users to
|
||||
* invoke a source->Connect (callback) method to perform the connection
|
||||
* explicitely, it was felt that this was a bit cumbersome to do.
|
||||
*
|
||||
* As such, the ``connection'' between a set of sources and a sink is
|
||||
* performed through a third-party class, the TraceResolver, which
|
||||
* can be used to automate the connection of multiple matching trace sources
|
||||
* to a single sink. This TraceResolver works by defining a hierarchical
|
||||
* tracing 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 current simulation models provide a '/nodes' tracing root.
|
||||
* This '/nodes' namespace is structured as follows:
|
||||
* \code
|
||||
* /nodes/n/arp
|
||||
* /nodes/n/udp
|
||||
* /nodes/n/ipv4
|
||||
* /tx
|
||||
* /rx
|
||||
* /drop
|
||||
* /interfaces/n/netdevice
|
||||
* /queue/
|
||||
* /enque
|
||||
* /deque
|
||||
* /drop
|
||||
* \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::NodeIndex 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::NodeIndex index;
|
||||
* context.Get (index);
|
||||
* std::cout << "node id=" << NodeList::GetNode (index)->GetId () << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* The hierarchical global namespace described here is not implemented
|
||||
* in a single central location: it was felt that doing this would make
|
||||
* it too hard to introduce user-specific models which could hook
|
||||
* automatically into the overal tracing system. If the tracing
|
||||
* namespace was implemented in a single central location, every model
|
||||
* author would have had to modify this central component to make
|
||||
* his own model available to trace users.
|
||||
*
|
||||
* Instead, the handling of the namespace is distributed across every relevant
|
||||
* model: every model implements only the part of the namespace it is
|
||||
* really responsible for. To do this, every model is expected
|
||||
* to provide an instance of a TraceResolver whose
|
||||
* responsability is to recursively provide access to the trace sources
|
||||
* defined in its model. Each TraceResolver instance should be a subclass
|
||||
* of the TraceResolver base class which implements either the DoLookup
|
||||
* or the DoConnect and DoDisconnect methods. Because implementing these
|
||||
* methods can be a bit tedious, our tracing framework provides a number
|
||||
* of helper template classes which should save the model author from
|
||||
* having to implement his 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. This step will obvsiouly depend on which model
|
||||
* contains your own model but, if you wrote a new l3 protocol, all you
|
||||
* would 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.
|
||||
*
|
||||
* So, in most cases, exporting a model's trace sources is a matter of
|
||||
* implementing a method CreateTraceResolver as shown below:
|
||||
* \code
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* enum TraceType {
|
||||
* TX,
|
||||
* RX,
|
||||
* ...
|
||||
* };
|
||||
* TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
* void Tx (Packet const &p);
|
||||
* private:
|
||||
* CallbackTraceSource<Packet const &> m_txTrace;
|
||||
* };
|
||||
*
|
||||
* TraceResolver *
|
||||
* MyModel::CreateTraceResolver (TraceContext const &context)
|
||||
* {
|
||||
* CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
* resolver->Add ("tx", m_txTrace, MyModel::TX);
|
||||
* return resolver;
|
||||
* }
|
||||
* void
|
||||
* MyModel::Tx (Packet const &p)
|
||||
* {
|
||||
* m_txTrace (p);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* 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/ *", callback);
|
||||
* traceContext = TraceContext ();
|
||||
* rootResolver = CompositeTraceResolver (traceContext);
|
||||
* rootResolver->Connect ("/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback);
|
||||
* resolver = CompositeTraceResolver::DoLookup ("nodes");
|
||||
* return NodeList::CreateTraceResolver (GetContext ());
|
||||
* return ArrayTraceResolver (context);
|
||||
* resolver->Connect ("/ * /ipv4/interfaces/ * /netdevice/queue/ *", callback);
|
||||
* ArrayTraceResolver::DoLookup ("*");
|
||||
* for (i = 0; i < n_nodes; i++)
|
||||
* resolver = nodes[i]->CreateTraceResolver (GetContext ());
|
||||
* return CompositeTraceResolver (context);
|
||||
* resolvers.add (resolver);
|
||||
* return resolvers;
|
||||
* for resolver in (resolvers)
|
||||
* resolver->Connect ("/ipv4/interfaces/ * /netdevice/queue/ *", callback);
|
||||
* CompositeTraceResolver::DoLookup ("ipv4");
|
||||
* resolver = ipv4->CreateTraceResolver (GetContext ());
|
||||
* return CompositeTraceResolver (context);
|
||||
* return resolver;
|
||||
* resolver->Connect ("/interfaces/ * /netdevice/queue/ *", callback);
|
||||
* CompositeTraceResolver::DoLookup ("interfaces");
|
||||
* resolver = ArrayTraceResolver (GetContext ());
|
||||
* resolver->Connect ("/ * /netdevice/queue/ *", callback);
|
||||
* ArrayTraceResolver::DoLookup ("*");
|
||||
* for (i = 0; i < n_interfaces; i++)
|
||||
* resolver = interfaces[i]->CreateTraceResolver (GetContext ());
|
||||
* return CompositeTraceResolver ()
|
||||
* resolvers.add (resolver);
|
||||
* return resolvers;
|
||||
* resolver->Connect ("/netdevice/queue/ *", callback);
|
||||
* CompositeTraceResolver::DoLookup ("netdevice");
|
||||
* resolver = NetDevice::CreateTraceResolver (GetContext ());
|
||||
* return CompositeTraceResolver ();
|
||||
* return resolver;
|
||||
* resolver->Connect ("/queue/ *", callback);
|
||||
* CompositeTraceResolver::DoLookup ("queue");
|
||||
* resolver = Queue::CreateTraceResolver (GetContext ());
|
||||
* return CompositeTraceResolver ();
|
||||
* return resolver
|
||||
* resolver->Connect ("*", callback);
|
||||
* CompositeTraceResolver::DoLookup ("*");
|
||||
* for match in (matches)
|
||||
* resolver = TerminalTraceResolver ("match");
|
||||
* resolvers.add (resolver)
|
||||
* return resolvers;
|
||||
* for resolver in (resolvers)
|
||||
* TerminalTraceResolver->DoConnect (callback);
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class CompositeTraceResolver;
|
||||
class TraceResolver;
|
||||
class TraceContext;
|
||||
class CallbackBase;
|
||||
|
||||
/**
|
||||
* \brief The main class used to access tracing functionality for
|
||||
* a user.
|
||||
*
|
||||
* \ingroup lowleveltracing
|
||||
*/
|
||||
class TraceRoot
|
||||
{
|
||||
public:
|
||||
static void Connect (std::string path, CallbackBase const &cb);
|
||||
static void Disconnect (std::string path, CallbackBase const &cb);
|
||||
static void Register (std::string name,
|
||||
Callback<TraceResolver *,TraceContext const &> createResolver);
|
||||
private:
|
||||
static CompositeTraceResolver *GetComposite (void);
|
||||
};
|
||||
|
||||
}// namespace ns3
|
||||
|
||||
#endif /* TRACE_ROOT_H */
|
||||
@@ -12,14 +12,6 @@ def build(bld):
|
||||
'tags.cc',
|
||||
'tag-registry.cc',
|
||||
'pcap-writer.cc',
|
||||
'variable-tracer-test.cc',
|
||||
'trace-context.cc',
|
||||
'trace-context-element.cc',
|
||||
'trace-resolver.cc',
|
||||
'callback-trace-source.cc',
|
||||
'empty-trace-resolver.cc',
|
||||
'composite-trace-resolver.cc',
|
||||
'trace-root.cc',
|
||||
'data-rate.cc',
|
||||
]
|
||||
|
||||
@@ -35,18 +27,6 @@ def build(bld):
|
||||
'packet.h',
|
||||
'packet-printer.h',
|
||||
'packet-metadata.h',
|
||||
'uv-trace-source.h',
|
||||
'sv-trace-source.h',
|
||||
'fv-trace-source.h',
|
||||
'pcap-writer.h',
|
||||
'callback-trace-source.h',
|
||||
'trace-context.h',
|
||||
'trace-context-element.h',
|
||||
'trace-resolver.h',
|
||||
'empty-trace-resolver.h',
|
||||
'composite-trace-resolver.h',
|
||||
'array-trace-resolver.h',
|
||||
'trace-root.h',
|
||||
'terminal-trace-resolver.h',
|
||||
'data-rate.h',
|
||||
]
|
||||
|
||||
205
src/core/array-trace-resolver.h
Normal file
205
src/core/array-trace-resolver.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef ARRAY_TRACE_RESOLVER_H
|
||||
#define ARRAY_TRACE_RESOLVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "callback.h"
|
||||
#include "trace-resolver.h"
|
||||
#include "object.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief a helper class to offer trace resolution for an array of objects.
|
||||
* \ingroup tracing
|
||||
*
|
||||
* \class ArrayTraceResolver
|
||||
*
|
||||
* An ArrayTraceResolver is a resolver which can match any input integer
|
||||
* against an element in an array. The array is accessed using a
|
||||
* pair iterators. Each element of the array is expected
|
||||
* to be a subclass of the Object base class.
|
||||
*
|
||||
* When the Connect method is called, this trace resolver will
|
||||
* automatically store in the TraceContext of each resolved object
|
||||
* its index through an object of type INDEX specified during the
|
||||
* instanciation of the ArrayTraceResolver template.
|
||||
*/
|
||||
template <typename INDEX>
|
||||
class ArrayTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
ArrayTraceResolver ();
|
||||
~ArrayTraceResolver ();
|
||||
|
||||
/**
|
||||
* \param begin an iterator which points to the start of the array.
|
||||
* \param end an iterator which points to the end of the array.
|
||||
*/
|
||||
template <typename T>
|
||||
void SetIterators (T begin, T end);
|
||||
|
||||
// inherited from TraceResolver
|
||||
virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
|
||||
virtual void Disconnect (std::string path, CallbackBase const &cb);
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection);
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context);
|
||||
|
||||
private:
|
||||
class IteratorBase
|
||||
{
|
||||
public:
|
||||
virtual ~IteratorBase () {}
|
||||
virtual void Next (void) = 0;
|
||||
virtual bool HasNext (void) = 0;
|
||||
virtual Ptr<Object> Get (void) = 0;
|
||||
virtual void Rewind (void) = 0;
|
||||
};
|
||||
IteratorBase *m_iter;
|
||||
};
|
||||
}//namespace ns3
|
||||
|
||||
|
||||
// implementation
|
||||
namespace ns3 {
|
||||
|
||||
template <typename INDEX>
|
||||
ArrayTraceResolver<INDEX>::ArrayTraceResolver ()
|
||||
: m_iter (0)
|
||||
{}
|
||||
|
||||
template <typename INDEX>
|
||||
ArrayTraceResolver<INDEX>::~ArrayTraceResolver ()
|
||||
{
|
||||
delete m_iter;
|
||||
}
|
||||
|
||||
template <typename INDEX>
|
||||
template <typename T>
|
||||
void
|
||||
ArrayTraceResolver<INDEX>::SetIterators (T begin, T end)
|
||||
{
|
||||
class Iterator : public IteratorBase
|
||||
{
|
||||
public:
|
||||
Iterator (T begin, T end)
|
||||
: m_begin (begin), m_end (end), m_cur (begin)
|
||||
{}
|
||||
virtual void Next (void)
|
||||
{m_cur++;}
|
||||
virtual bool HasNext (void)
|
||||
{return m_cur != m_end;}
|
||||
virtual Ptr<Object> Get (void)
|
||||
{return *m_cur;}
|
||||
virtual void Rewind (void)
|
||||
{m_cur = m_begin;}
|
||||
private:
|
||||
T m_begin;
|
||||
T m_end;
|
||||
T m_cur;
|
||||
};
|
||||
delete m_iter;
|
||||
m_iter = new Iterator (begin, end);
|
||||
}
|
||||
|
||||
template <typename INDEX>
|
||||
void
|
||||
ArrayTraceResolver<INDEX>::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
|
||||
{
|
||||
if (path == "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::string id = GetElement (path);
|
||||
std::string subpath = GetSubpath (path);
|
||||
if (id == "*")
|
||||
{
|
||||
uint32_t j = 0;
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
TraceContext tmp = context;
|
||||
INDEX index = j;
|
||||
tmp.AddElement (index);
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename INDEX>
|
||||
void
|
||||
ArrayTraceResolver<INDEX>::Disconnect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
if (path == "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::string id = GetElement (path);
|
||||
std::string subpath = GetSubpath (path);
|
||||
if (id == "*")
|
||||
{
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->TraceDisconnect (subpath, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename INDEX>
|
||||
void
|
||||
ArrayTraceResolver<INDEX>::CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
path.append ("/[0-n]");
|
||||
uint32_t j = 0;
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
TraceContext tmp = context;
|
||||
INDEX index = j;
|
||||
tmp.AddElement (index);
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->GetTraceResolver ()->CollectSources (path, tmp, collection);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename INDEX>
|
||||
void
|
||||
ArrayTraceResolver<INDEX>::TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
uint32_t j = 0;
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
TraceContext tmp = context;
|
||||
INDEX index = j;
|
||||
tmp.AddElement (index);
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->GetTraceResolver ()->TraceAll (os, tmp);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* ARRAY_TRACE_RESOLVER_H */
|
||||
@@ -57,6 +57,21 @@ void *Test10 (bool *a, int const & b)
|
||||
return a;
|
||||
}
|
||||
|
||||
void TestFZero (void) {}
|
||||
void TestFOne (int) {}
|
||||
void TestFTwo (int, int) {}
|
||||
void TestFThree (int, int, int) {}
|
||||
void TestFFour (int, int, int, int) {}
|
||||
void TestFFive (int, int, int, int, int) {}
|
||||
void TestFSix (int, int, int, int, int, int) {}
|
||||
|
||||
void TestFROne (int &) {}
|
||||
void TestFRTwo (int &, int &) {}
|
||||
void TestFRThree (int &, int &, int &) {}
|
||||
void TestFRFour (int &, int &, int &, int &) {}
|
||||
void TestFRFive (int &, int &, int &, int &, int &) {}
|
||||
void TestFRSix (int &, int &, int &, int &, int &, int &) {}
|
||||
|
||||
class CallbackTest : public ns3::Test {
|
||||
private:
|
||||
bool m_test1;
|
||||
@@ -73,6 +88,22 @@ public:
|
||||
void Test3 (double a);
|
||||
int Test4 (double a, int b);
|
||||
void Test8 (Callback<void, int> callback);
|
||||
|
||||
void TestZero (void) {}
|
||||
void TestOne (int) {}
|
||||
void TestTwo (int, int) {}
|
||||
void TestThree (int, int, int) {}
|
||||
void TestFour (int, int, int, int) {}
|
||||
void TestFive (int, int, int, int, int) {}
|
||||
void TestSix (int, int, int, int, int, int) {}
|
||||
|
||||
void TestCZero (void) const {}
|
||||
void TestCOne (int) const {}
|
||||
void TestCTwo (int, int) const {}
|
||||
void TestCThree (int, int, int) const {}
|
||||
void TestCFour (int, int, int, int) const {}
|
||||
void TestCFive (int, int, int, int, int) const {}
|
||||
void TestCSix (int, int, int, int, int, int) const {}
|
||||
};
|
||||
|
||||
CallbackTest::CallbackTest ()
|
||||
@@ -110,6 +141,7 @@ CallbackTest::Test8 (Callback<void,int> callback)
|
||||
{
|
||||
callback (3);
|
||||
}
|
||||
|
||||
bool
|
||||
CallbackTest::IsWrong (void)
|
||||
{
|
||||
@@ -216,6 +248,53 @@ CallbackTest::RunTests (void)
|
||||
MakeBoundCallback (&Test9, &v);
|
||||
MakeBoundCallback (&Test10, &v);
|
||||
|
||||
|
||||
MakeCallback (&CallbackTest::TestZero, this);
|
||||
MakeCallback (&CallbackTest::TestOne, this);
|
||||
MakeCallback (&CallbackTest::TestTwo, this);
|
||||
MakeCallback (&CallbackTest::TestThree, this);
|
||||
MakeCallback (&CallbackTest::TestFour, this);
|
||||
MakeCallback (&CallbackTest::TestFive, this);
|
||||
MakeCallback (&CallbackTest::TestSix, this);
|
||||
|
||||
MakeCallback (&CallbackTest::TestCZero, this);
|
||||
MakeCallback (&CallbackTest::TestCOne, this);
|
||||
MakeCallback (&CallbackTest::TestCTwo, this);
|
||||
MakeCallback (&CallbackTest::TestCThree, this);
|
||||
MakeCallback (&CallbackTest::TestCFour, this);
|
||||
MakeCallback (&CallbackTest::TestCFive, this);
|
||||
MakeCallback (&CallbackTest::TestCSix, this);
|
||||
|
||||
MakeCallback (&TestFZero);
|
||||
MakeCallback (&TestFOne);
|
||||
MakeCallback (&TestFTwo);
|
||||
MakeCallback (&TestFThree);
|
||||
MakeCallback (&TestFFour);
|
||||
MakeCallback (&TestFFive);
|
||||
MakeCallback (&TestFSix);
|
||||
|
||||
MakeCallback (&TestFROne);
|
||||
MakeCallback (&TestFRTwo);
|
||||
MakeCallback (&TestFRThree);
|
||||
MakeCallback (&TestFRFour);
|
||||
MakeCallback (&TestFRFive);
|
||||
MakeCallback (&TestFRSix);
|
||||
|
||||
|
||||
MakeBoundCallback (&TestFOne, 1);
|
||||
MakeBoundCallback (&TestFTwo, 1);
|
||||
MakeBoundCallback (&TestFThree, 1);
|
||||
MakeBoundCallback (&TestFFour, 1);
|
||||
MakeBoundCallback (&TestFFive, 1);
|
||||
|
||||
MakeBoundCallback (&TestFROne, 1);
|
||||
MakeBoundCallback (&TestFRTwo, 1);
|
||||
MakeBoundCallback (&TestFRThree, 1);
|
||||
MakeBoundCallback (&TestFRFour, 1);
|
||||
MakeBoundCallback (&TestFRFive, 1);
|
||||
|
||||
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "callback-trace-source.h"
|
||||
#include "ns3/test.h"
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
|
||||
#include "test.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -55,7 +58,7 @@ CallbackTraceSourceTest::CbTwo (TraceContext const &context, uint8_t a, double b
|
||||
bool
|
||||
CallbackTraceSourceTest::RunTests (void)
|
||||
{
|
||||
bool ok = true;
|
||||
bool result = true;
|
||||
TraceContext ctx;
|
||||
|
||||
CallbackTraceSource<uint8_t,double> trace;
|
||||
@@ -64,32 +67,35 @@ CallbackTraceSourceTest::RunTests (void)
|
||||
m_one = false;
|
||||
m_two = false;
|
||||
trace (1, 2);
|
||||
if (!m_one || !m_two)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT (m_one);
|
||||
NS_TEST_ASSERT (m_two);
|
||||
|
||||
trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this));
|
||||
m_one = false;
|
||||
m_two = false;
|
||||
trace (1, 2);
|
||||
if (m_one || !m_two)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT (!m_one);
|
||||
NS_TEST_ASSERT (m_two);
|
||||
trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this));
|
||||
m_one = false;
|
||||
m_two = false;
|
||||
trace (1, 2);
|
||||
if (m_one || m_two)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT (!m_one);
|
||||
NS_TEST_ASSERT (!m_two);
|
||||
|
||||
return ok;
|
||||
trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this), ctx);
|
||||
trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this), ctx);
|
||||
m_one = false;
|
||||
m_two = false;
|
||||
trace (1, 2);
|
||||
NS_TEST_ASSERT (m_one);
|
||||
NS_TEST_ASSERT (m_two);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CallbackTraceSourceTest g_callbackTraceTest;
|
||||
|
||||
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* RUN_SELF_TESTS */
|
||||
251
src/core/callback-trace-source.h
Normal file
251
src/core/callback-trace-source.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006,2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef CALLBACK_TRACE_H
|
||||
#define CALLBACK_TRACE_H
|
||||
|
||||
#include <list>
|
||||
#include "callback.h"
|
||||
#include "fatal-error.h"
|
||||
#include "trace-context.h"
|
||||
#include "trace-source.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief log arbitrary number of parameters to a matching ns3::Callback
|
||||
* \ingroup tracing
|
||||
*
|
||||
* Whenever operator () is invoked on this class, the call and its arguments
|
||||
* are forwarded to the internal matching ns3::Callback.
|
||||
*/
|
||||
template<typename T1 = empty, typename T2 = empty,
|
||||
typename T3 = empty, typename T4 = empty>
|
||||
class CallbackTraceSource : public TraceSource {
|
||||
public:
|
||||
CallbackTraceSource ();
|
||||
virtual void AddCallback (CallbackBase const & callback, TraceContext const & context);
|
||||
virtual void RemoveCallback (CallbackBase const & callback);
|
||||
virtual void ConnectPrinter (std::ostream &os, const TraceContext &context);
|
||||
void operator() (void) const;
|
||||
void operator() (T1 a1) const;
|
||||
void operator() (T1 a1, T2 a2) const;
|
||||
void operator() (T1 a1, T2 a2, T3 a3) const;
|
||||
void operator() (T1 a1, T2 a2, T3 a3, T4 a4) const;
|
||||
|
||||
private:
|
||||
typedef std::list<Callback<void,TraceContext const &,T1,T2,T3,T4> > CallbackList;
|
||||
TraceContext m_context;
|
||||
CallbackList m_callbackList;
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
// implementation below.
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
class TraceSinkPrint;
|
||||
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
class TraceSinkPrint
|
||||
{
|
||||
public:
|
||||
static Callback<void,const TraceContext &,T1,T2,T3,T4> Make (std::ostream &os)
|
||||
{
|
||||
return ns3::MakeBoundCallback (&DoPrint, &os);
|
||||
}
|
||||
private:
|
||||
static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
*os << "context=\"" << context << "\" arg1=\"" << a1 << "\" arg2=\"" << a2 << "\" arg3=\"" << a3 << "\" arg4=\"" << a4 << "\"" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2,
|
||||
typename T3>
|
||||
class TraceSinkPrint<T1,T2,T3,empty>
|
||||
{
|
||||
public:
|
||||
static Callback<void,const TraceContext &,T1,T2,T3> Make (std::ostream &os)
|
||||
{
|
||||
return ns3::MakeBoundCallback (&DoPrint, &os);
|
||||
}
|
||||
private:
|
||||
static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
*os << "context=\"" << context << "\" arg1=\"" << a1 << "\" arg2=\"" << a2 << "\" arg3=\"" << a3 << "\"" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
class TraceSinkPrint<T1,T2,empty,empty>
|
||||
{
|
||||
public:
|
||||
static Callback<void,const TraceContext &,T1,T2> Make (std::ostream &os)
|
||||
{
|
||||
return ns3::MakeBoundCallback (&DoPrint, &os);
|
||||
}
|
||||
private:
|
||||
static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1, T2 a2)
|
||||
{
|
||||
*os << "context=\"" << context << "\" arg1=\"" << a1 << "\" arg2=\"" << a2 << "\"" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1>
|
||||
class TraceSinkPrint<T1,empty,empty,empty>
|
||||
{
|
||||
public:
|
||||
static Callback<void,const TraceContext &,T1> Make (std::ostream &os)
|
||||
{
|
||||
return ns3::MakeBoundCallback (&DoPrint, &os);
|
||||
}
|
||||
private:
|
||||
static void DoPrint (std::ostream *os, const TraceContext &context, T1 a1)
|
||||
{
|
||||
*os << "context=\"" << context << "\" arg1=\"" << a1 << "\"" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class TraceSinkPrint<empty,empty,empty,empty>
|
||||
{
|
||||
public:
|
||||
static Callback<void,const TraceContext &> Make (std::ostream &os)
|
||||
{
|
||||
return ns3::MakeBoundCallback (&DoPrint, &os);
|
||||
}
|
||||
private:
|
||||
static void DoPrint (std::ostream *os, const TraceContext &context)
|
||||
{
|
||||
*os << "context=\"" << context << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
CallbackTraceSource<T1,T2,T3,T4>::CallbackTraceSource ()
|
||||
: m_callbackList ()
|
||||
{}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::AddCallback (CallbackBase const & callback,
|
||||
TraceContext const &context)
|
||||
{
|
||||
Callback<void,TraceContext const &,T1,T2,T3,T4> cb;
|
||||
cb.Assign (callback);
|
||||
m_context.Union (context);
|
||||
m_callbackList.push_back (cb);
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::RemoveCallback (CallbackBase const & callback)
|
||||
{
|
||||
for (typename CallbackList::iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); /* empty */)
|
||||
{
|
||||
if ((*i).IsEqual (callback))
|
||||
{
|
||||
i = m_callbackList.erase (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::ConnectPrinter (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
AddCallback (ns3::internal::TraceSinkPrint<T1,T2,T3,T4>::Make (os), context);
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (void) const
|
||||
{
|
||||
for (typename CallbackList::const_iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1) const
|
||||
{
|
||||
for (typename CallbackList::const_iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2) const
|
||||
{
|
||||
for (typename CallbackList::const_iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1, a2);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3) const
|
||||
{
|
||||
for (typename CallbackList::const_iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1, a2, a3);
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2,
|
||||
typename T3, typename T4>
|
||||
void
|
||||
CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3, T4 a4) const
|
||||
{
|
||||
for (typename CallbackList::const_iterator i = m_callbackList.begin ();
|
||||
i != m_callbackList.end (); i++)
|
||||
{
|
||||
(*i) (m_context, a1, a2, a3, a4);
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* CALLBACK_TRACE_H */
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ptr.h"
|
||||
#include "fatal-error.h"
|
||||
#include "empty.h"
|
||||
#include "type-traits.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -89,55 +90,62 @@ private:
|
||||
};
|
||||
|
||||
// declare the CallbackImpl class
|
||||
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
||||
class CallbackImpl;
|
||||
// define CallbackImpl for 0 params
|
||||
template <typename R>
|
||||
class CallbackImpl<R,empty,empty,empty,empty,empty> : public CallbackImplBase {
|
||||
class CallbackImpl<R,empty,empty,empty,empty,empty,empty> : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (void) = 0;
|
||||
};
|
||||
// define CallbackImpl for 1 params
|
||||
template <typename R, typename T1>
|
||||
class CallbackImpl<R,T1,empty,empty,empty,empty> : public CallbackImplBase {
|
||||
class CallbackImpl<R,T1,empty,empty,empty,empty,empty> : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (T1) = 0;
|
||||
};
|
||||
// define CallbackImpl for 2 params
|
||||
template <typename R, typename T1, typename T2>
|
||||
class CallbackImpl<R,T1,T2,empty,empty,empty> : public CallbackImplBase {
|
||||
class CallbackImpl<R,T1,T2,empty,empty,empty,empty> : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (T1, T2) = 0;
|
||||
};
|
||||
// define CallbackImpl for 3 params
|
||||
template <typename R, typename T1, typename T2, typename T3>
|
||||
class CallbackImpl<R,T1,T2,T3,empty,empty> : public CallbackImplBase {
|
||||
class CallbackImpl<R,T1,T2,T3,empty,empty,empty> : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (T1, T2, T3) = 0;
|
||||
};
|
||||
// define CallbackImpl for 4 params
|
||||
template <typename R, typename T1, typename T2, typename T3, typename T4>
|
||||
class CallbackImpl<R,T1,T2,T3,T4,empty> : public CallbackImplBase {
|
||||
class CallbackImpl<R,T1,T2,T3,T4,empty,empty> : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (T1, T2, T3, T4) = 0;
|
||||
};
|
||||
// define CallbackImpl for 5 params
|
||||
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
class CallbackImpl : public CallbackImplBase {
|
||||
class CallbackImpl<R,T1,T2,T3,T4,T5,empty> : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (T1, T2, T3, T4, T5) = 0;
|
||||
};
|
||||
// define CallbackImpl for 6 params
|
||||
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
||||
class CallbackImpl : public CallbackImplBase {
|
||||
public:
|
||||
virtual ~CallbackImpl () {}
|
||||
virtual R operator() (T1, T2, T3, T4, T5, T6) = 0;
|
||||
};
|
||||
|
||||
|
||||
// an impl for Functors:
|
||||
template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
|
||||
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
|
||||
template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6>
|
||||
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6> {
|
||||
public:
|
||||
FunctorCallbackImpl (T const &functor)
|
||||
: m_functor (functor) {}
|
||||
@@ -160,9 +168,12 @@ public:
|
||||
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
|
||||
return m_functor (a1,a2,a3,a4,a5);
|
||||
}
|
||||
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) {
|
||||
return m_functor (a1,a2,a3,a4,a5,a6);
|
||||
}
|
||||
virtual bool IsEqual (CallbackImplBase const *other) const {
|
||||
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *otherDerived =
|
||||
dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *> (other);
|
||||
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6> const *otherDerived =
|
||||
dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6> const *> (other);
|
||||
if (otherDerived == 0)
|
||||
{
|
||||
return false;
|
||||
@@ -178,8 +189,8 @@ private:
|
||||
};
|
||||
|
||||
// an impl for pointer to member functions
|
||||
template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
|
||||
template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
||||
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6> {
|
||||
public:
|
||||
MemPtrCallbackImpl (OBJ_PTR const&objPtr, MEM_PTR mem_ptr)
|
||||
: m_objPtr (objPtr), m_memPtr (mem_ptr) {}
|
||||
@@ -202,9 +213,12 @@ public:
|
||||
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
|
||||
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5);
|
||||
}
|
||||
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) {
|
||||
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
virtual bool IsEqual (CallbackImplBase const *other) const {
|
||||
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *otherDerived =
|
||||
dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *> (other);
|
||||
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> const *otherDerived =
|
||||
dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> const *> (other);
|
||||
if (otherDerived == 0)
|
||||
{
|
||||
return false;
|
||||
@@ -260,22 +274,22 @@ public:
|
||||
template<typename R,
|
||||
typename T1 = empty, typename T2 = empty,
|
||||
typename T3 = empty, typename T4 = empty,
|
||||
typename T5 = empty>
|
||||
typename T5 = empty, typename T6 = empty>
|
||||
class Callback : public CallbackBase {
|
||||
public:
|
||||
// There are two dummy args below to ensure that this constructor is
|
||||
// always properly disambiguited by the c++ compiler
|
||||
template <typename FUNCTOR>
|
||||
Callback (FUNCTOR const &functor, bool, bool)
|
||||
: m_impl (Create<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> > (functor))
|
||||
: m_impl (Create<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5,T6> > (functor))
|
||||
{}
|
||||
|
||||
template <typename OBJ_PTR, typename MEM_PTR>
|
||||
Callback (OBJ_PTR const &objPtr, MEM_PTR mem_ptr)
|
||||
: m_impl (Create<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> > (objPtr, mem_ptr))
|
||||
: m_impl (Create<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6> > (objPtr, mem_ptr))
|
||||
{}
|
||||
|
||||
Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > const &impl)
|
||||
Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6> > const &impl)
|
||||
: m_impl (impl)
|
||||
{}
|
||||
|
||||
@@ -305,14 +319,17 @@ public:
|
||||
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const {
|
||||
return (*(PeekImpl ())) (a1,a2,a3,a4,a5);
|
||||
}
|
||||
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5,T6 a6) const {
|
||||
return (*(PeekImpl ())) (a1,a2,a3,a4,a5,a6);
|
||||
}
|
||||
|
||||
bool IsEqual (CallbackBase const &other) {
|
||||
bool IsEqual (CallbackBase const &other) const {
|
||||
return PeekImpl ()->IsEqual (other.PeekImpl ());
|
||||
}
|
||||
|
||||
bool CheckType (CallbackBase const& other) {
|
||||
bool CheckType (CallbackBase const& other) const {
|
||||
CallbackImplBase *otherBase = other.PeekImpl ();
|
||||
if (dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5> *> (otherBase) != 0)
|
||||
if (dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6> *> (otherBase) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -328,27 +345,27 @@ public:
|
||||
" got=" << typeid (other).name () <<
|
||||
", expected=" << typeid (*this).name ());
|
||||
}
|
||||
const Callback<R, T1,T2,T3,T4,T5> *goodType = static_cast<const Callback<R,T1,T2,T3,T4,T5> *> (&other);
|
||||
const Callback<R, T1,T2,T3,T4,T5,T6> *goodType = static_cast<const Callback<R,T1,T2,T3,T4,T5,T6> *> (&other);
|
||||
*this = *goodType;
|
||||
}
|
||||
void Assign (Ptr<CallbackImplBase> other) {
|
||||
CallbackImpl<R,T1,T2,T3,T4,T5> *impl = dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5> *> (PeekPointer (other));
|
||||
CallbackImpl<R,T1,T2,T3,T4,T5,T6> *impl = dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6> *> (PeekPointer (other));
|
||||
if (other == 0)
|
||||
{
|
||||
NS_FATAL_ERROR ("Incompatible types. (feed to \"c++filt -t\")"
|
||||
" got=" << typeid (other).name () <<
|
||||
", expected=" << typeid (*impl).name ());
|
||||
}
|
||||
*this = Callback<R,T1,T2,T3,T4,T5> (impl);
|
||||
*this = Callback<R,T1,T2,T3,T4,T5,T6> (impl);
|
||||
}
|
||||
virtual Ptr<CallbackImplBase>GetImpl (void) const {
|
||||
return m_impl;
|
||||
}
|
||||
private:
|
||||
virtual CallbackImpl<R,T1,T2,T3,T4,T5> *PeekImpl (void) const {
|
||||
virtual CallbackImpl<R,T1,T2,T3,T4,T5,T6> *PeekImpl (void) const {
|
||||
return PeekPointer (m_impl);
|
||||
}
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > m_impl;
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6> > m_impl;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -369,7 +386,7 @@ Callback<R> MakeCallback (R (T::*memPtr) (void), OBJ objPtr) {
|
||||
return Callback<R> (objPtr, memPtr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R>
|
||||
Callback<R> MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) {
|
||||
Callback<R> MakeCallback (R (T::*mem_ptr) () const, OBJ objPtr) {
|
||||
return Callback<R> (objPtr, mem_ptr);
|
||||
}
|
||||
/**
|
||||
@@ -381,11 +398,11 @@ Callback<R> MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) {
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename T, typename OBJ, typename R, typename T1>
|
||||
Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1), OBJ *const objPtr) {
|
||||
Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1), OBJ objPtr) {
|
||||
return Callback<R,T1> (objPtr, mem_ptr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R, typename T1>
|
||||
Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr) {
|
||||
Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1) const, OBJ objPtr) {
|
||||
return Callback<R,T1> (objPtr, mem_ptr);
|
||||
}
|
||||
/**
|
||||
@@ -397,11 +414,11 @@ Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2>
|
||||
Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ *const objPtr) {
|
||||
Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ objPtr) {
|
||||
return Callback<R,T1,T2> (objPtr, mem_ptr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2>
|
||||
Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) {
|
||||
Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ objPtr) {
|
||||
return Callback<R,T1,T2> (objPtr, mem_ptr);
|
||||
}
|
||||
/**
|
||||
@@ -413,11 +430,11 @@ Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const o
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename T, typename OBJ, typename R, typename T1,typename T2, typename T3>
|
||||
Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) {
|
||||
Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3> (objPtr, mem_ptr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R, typename T1,typename T2, typename T3>
|
||||
Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) {
|
||||
Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3> (objPtr, mem_ptr);
|
||||
}
|
||||
/**
|
||||
@@ -429,11 +446,11 @@ Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*c
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
|
||||
Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) {
|
||||
Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3,T4> (objPtr, mem_ptr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
|
||||
Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) {
|
||||
Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3,T4> (objPtr, mem_ptr);
|
||||
}
|
||||
/**
|
||||
@@ -445,13 +462,29 @@ Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ c
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) {
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3,T4,T5> (objPtr, mem_ptr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) {
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3,T4,T5> (objPtr, mem_ptr);
|
||||
}
|
||||
/**
|
||||
* \ingroup MakeCallback
|
||||
* \param mem_ptr class method member pointer
|
||||
* \param objPtr class instance
|
||||
* \return a wrapper Callback
|
||||
* Build Callbacks for class method members which takes five arguments
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5,typename T6>
|
||||
Callback<R,T1,T2,T3,T4,T5,T6> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5,T6), OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3,T4,T5,T6> (objPtr, mem_ptr);
|
||||
}
|
||||
template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6>
|
||||
Callback<R,T1,T2,T3,T4,T5,T6> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5,T6) const, OBJ objPtr) {
|
||||
return Callback<R,T1,T2,T3,T4,T5,T6> (objPtr, mem_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup MakeCallback
|
||||
@@ -519,6 +552,17 @@ template <typename R, typename T1, typename T2,typename T3,typename T4,typename
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) {
|
||||
return Callback<R,T1,T2,T3,T4,T5> (fnPtr, true, true);
|
||||
}
|
||||
/**
|
||||
* \ingroup MakeCallback
|
||||
* \param fnPtr function pointer
|
||||
* \return a wrapper Callback
|
||||
* Build Callbacks for functions which takes five arguments
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5,typename T6>
|
||||
Callback<R,T1,T2,T3,T4,T5,T6> MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5,T6)) {
|
||||
return Callback<R,T1,T2,T3,T4,T5,T6> (fnPtr, true, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -587,6 +631,17 @@ template <typename R, typename T1, typename T2,typename T3,typename T4,typename
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeNullCallback (void) {
|
||||
return Callback<R,T1,T2,T3,T4,T5> ();
|
||||
}
|
||||
/**
|
||||
* \ingroup MakeCallback
|
||||
* \overload Callback<R> MakeNullCallback (void)
|
||||
* \return a wrapper Callback
|
||||
* Build a null callback which takes five arguments
|
||||
* and potentially return a value.
|
||||
*/
|
||||
template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5,typename T6>
|
||||
Callback<R,T1,T2,T3,T4,T5,T6> MakeNullCallback (void) {
|
||||
return Callback<R,T1,T2,T3,T4,T5,T6> ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -596,9 +651,10 @@ Callback<R,T1,T2,T3,T4,T5> MakeNullCallback (void) {
|
||||
*/
|
||||
// an impl for Bound Functors:
|
||||
template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5>
|
||||
class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
|
||||
class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,empty> {
|
||||
public:
|
||||
BoundFunctorCallbackImpl (T const &functor, TX a)
|
||||
template <typename FUNCTOR, typename ARG>
|
||||
BoundFunctorCallbackImpl (FUNCTOR functor, ARG a)
|
||||
: m_functor (functor), m_a (a) {}
|
||||
virtual ~BoundFunctorCallbackImpl () {}
|
||||
R operator() (void) {
|
||||
@@ -635,38 +691,48 @@ public:
|
||||
}
|
||||
private:
|
||||
T m_functor;
|
||||
TX m_a;
|
||||
typename TypeTraits<TX>::ReferencedType m_a;
|
||||
};
|
||||
|
||||
template <typename R, typename TX>
|
||||
Callback<R> MakeBoundCallback (R (*fnPtr) (TX), TX a) {
|
||||
Ptr<CallbackImpl<R,empty,empty,empty,empty,empty> > impl =
|
||||
template <typename R, typename TX, typename ARG>
|
||||
Callback<R> MakeBoundCallback (R (*fnPtr) (TX), ARG a) {
|
||||
Ptr<CallbackImpl<R,empty,empty,empty,empty,empty,empty> > impl =
|
||||
Create<BoundFunctorCallbackImpl<R (*) (TX),R,TX,empty,empty,empty,empty,empty> >(fnPtr, a);
|
||||
return Callback<R> (impl);
|
||||
}
|
||||
|
||||
template <typename R, typename TX, typename T1>
|
||||
Callback<R,T1> MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) {
|
||||
Ptr<CallbackImpl<R,T1,empty,empty,empty,empty> > impl =
|
||||
template <typename R, typename TX, typename ARG,
|
||||
typename T1>
|
||||
Callback<R,T1> MakeBoundCallback (R (*fnPtr) (TX,T1), ARG a) {
|
||||
Ptr<CallbackImpl<R,T1,empty,empty,empty,empty,empty> > impl =
|
||||
Create<BoundFunctorCallbackImpl<R (*) (TX,T1),R,TX,T1,empty,empty,empty,empty> > (fnPtr, a);
|
||||
return Callback<R,T1> (impl);
|
||||
}
|
||||
template <typename R, typename TX, typename T1, typename T2>
|
||||
Callback<R,T1,T2> MakeBoundCallback (R (*fnPtr) (TX,T1,T2), TX a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,empty,empty,empty> > impl =
|
||||
template <typename R, typename TX, typename ARG,
|
||||
typename T1, typename T2>
|
||||
Callback<R,T1,T2> MakeBoundCallback (R (*fnPtr) (TX,T1,T2), ARG a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,empty,empty,empty,empty> > impl =
|
||||
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2),R,TX,T1,T2,empty,empty,empty> > (fnPtr, a);
|
||||
return Callback<R,T1,T2> (impl);
|
||||
}
|
||||
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4>
|
||||
Callback<R,T1,T2,T3,T4> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), TX a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,T4,empty> > impl =
|
||||
template <typename R, typename TX, typename ARG,
|
||||
typename T1, typename T2,typename T3>
|
||||
Callback<R,T1,T2,T3> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3), ARG a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,empty,empty,empty> > impl =
|
||||
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3),R,TX,T1,T2,T3,empty,empty> > (fnPtr, a);
|
||||
return Callback<R,T1,T2,T3> (impl);
|
||||
}
|
||||
template <typename R, typename TX, typename ARG,
|
||||
typename T1, typename T2,typename T3,typename T4>
|
||||
Callback<R,T1,T2,T3,T4> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), ARG a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,T4,empty,empty> > impl =
|
||||
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4),R,TX,T1,T2,T3,T4,empty> > (fnPtr, a);
|
||||
return Callback<R,T1,T2,T3,T4> (impl);
|
||||
}
|
||||
|
||||
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4,typename T5>
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), TX a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > impl =
|
||||
template <typename R, typename TX, typename ARG,
|
||||
typename T1, typename T2,typename T3,typename T4,typename T5>
|
||||
Callback<R,T1,T2,T3,T4,T5> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), ARG a) {
|
||||
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,empty> > impl =
|
||||
Create<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4,T5),R,TX,T1,T2,T3,T4,T5> > (fnPtr, a);
|
||||
return Callback<R,T1,T2,T3,T4,T5> (impl);
|
||||
}
|
||||
|
||||
595
src/core/composite-trace-resolver.cc
Normal file
595
src/core/composite-trace-resolver.cc
Normal file
@@ -0,0 +1,595 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "composite-trace-resolver.h"
|
||||
#include "debug.h"
|
||||
|
||||
NS_DEBUG_COMPONENT_DEFINE ("CompositeTraceResolver");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
CompositeTraceResolver::CompositeTraceResolver ()
|
||||
{}
|
||||
|
||||
CompositeTraceResolver::~CompositeTraceResolver ()
|
||||
{
|
||||
for (TraceItems::iterator i = m_items.begin (); i != m_items.end (); i++)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
m_items.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::AddItem (ResolveItem *item)
|
||||
{
|
||||
m_items.push_back (item);
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::Add (std::string name,
|
||||
Callback<Ptr<TraceResolver> > createResolver)
|
||||
{
|
||||
class MakerResolveItem : public ResolveItem
|
||||
{
|
||||
public:
|
||||
virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context)
|
||||
{maker ()->Connect (subpath, cb, context);}
|
||||
virtual void Disconnect (std::string subpath, const CallbackBase &cb)
|
||||
{maker ()->Disconnect (subpath, cb);}
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
path.append ("/");
|
||||
path.append (this->name);
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
this->maker ()->CollectSources (path, ctx, collection);
|
||||
}
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
this->maker ()->TraceAll (os, ctx);
|
||||
}
|
||||
Callback<Ptr<TraceResolver> > maker;
|
||||
} *item = new MakerResolveItem ();
|
||||
item->name = name;
|
||||
item->context = TraceContext ();
|
||||
item->maker = createResolver;
|
||||
AddItem (item);
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::AddSource (std::string name,
|
||||
const TraceDoc &doc,
|
||||
const TraceSource &trace)
|
||||
{
|
||||
DoAddSource (name, doc, trace, TraceContext ());
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::DoAddSource (std::string name,
|
||||
const TraceDoc &doc,
|
||||
const TraceSource &trace,
|
||||
const TraceContext &context)
|
||||
{
|
||||
class SourceResolveItem : public ResolveItem
|
||||
{
|
||||
public:
|
||||
virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context)
|
||||
{if (subpath == "") {trace->AddCallback (cb, context);}}
|
||||
virtual void Disconnect (std::string subpath, const CallbackBase &cb)
|
||||
{if (subpath == "") {trace->RemoveCallback (cb);}}
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
path.append ("/");
|
||||
path.append (this->name);
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
collection->AddUnique (path, ctx, this->doc);
|
||||
}
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
this->trace->ConnectPrinter (os, ctx);
|
||||
}
|
||||
TraceSource *trace;
|
||||
TraceDoc doc;
|
||||
} *item = new SourceResolveItem ();
|
||||
item->name = name;
|
||||
item->context = context;
|
||||
item->trace = const_cast<TraceSource *> (&trace);
|
||||
item->doc = doc;
|
||||
AddItem (item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
CompositeTraceResolver::AddComposite (std::string name, Ptr<Object> composite)
|
||||
{
|
||||
DoAddComposite (name, composite, TraceContext ());
|
||||
}
|
||||
void
|
||||
CompositeTraceResolver::DoAddComposite (std::string name, Ptr<Object> composite, const TraceContext &context)
|
||||
{
|
||||
class CompositeResolveItem : public ResolveItem
|
||||
{
|
||||
public:
|
||||
virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context)
|
||||
{composite->GetTraceResolver ()->Connect (subpath, cb, context);}
|
||||
virtual void Disconnect (std::string subpath, const CallbackBase &cb)
|
||||
{composite->TraceDisconnect (subpath, cb);}
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
path.append ("/");
|
||||
path.append (this->name);
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
this->composite->GetTraceResolver ()->CollectSources (path, ctx, collection);
|
||||
}
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
this->composite->GetTraceResolver ()->TraceAll (os, ctx);
|
||||
}
|
||||
|
||||
Ptr<Object> composite;
|
||||
} *item = new CompositeResolveItem ();
|
||||
item->name = name;
|
||||
item->context = context;
|
||||
item->composite = composite;
|
||||
AddItem (item);
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::SetParentResolver (Ptr<TraceResolver> resolver)
|
||||
{
|
||||
m_parent = resolver;
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
|
||||
{
|
||||
NS_DEBUG ("connect path="<<path);
|
||||
class ConnectOperation : public Operation
|
||||
{
|
||||
public:
|
||||
ConnectOperation (const CallbackBase &cb, const TraceContext &context)
|
||||
: m_cb (cb), m_context (context)
|
||||
{}
|
||||
virtual void Do (std::string subpath, ResolveItem *item) const
|
||||
{
|
||||
NS_DEBUG ("connect to path="<<subpath<<" name="<<item->name);
|
||||
TraceContext context = m_context;
|
||||
context.Union (item->context);
|
||||
item->Connect (subpath, m_cb, context);
|
||||
}
|
||||
virtual void DoParent (std::string path, Ptr<TraceResolver> parent) const
|
||||
{
|
||||
if (parent != 0)
|
||||
{
|
||||
parent->Connect (path, m_cb, m_context);
|
||||
}
|
||||
}
|
||||
private:
|
||||
const CallbackBase &m_cb;
|
||||
const TraceContext &m_context;
|
||||
} operation = ConnectOperation (cb, context);
|
||||
DoRecursiveOperation (path, operation);
|
||||
}
|
||||
void
|
||||
CompositeTraceResolver::DoRecursiveOperation (std::string path,
|
||||
const Operation &operation)
|
||||
{
|
||||
if (path == "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::string id = GetElement (path);
|
||||
std::string subpath = GetSubpath (path);
|
||||
|
||||
if (id == "*")
|
||||
{
|
||||
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
|
||||
{
|
||||
operation.Do (subpath, *i);
|
||||
}
|
||||
operation.DoParent (path, m_parent);
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
operation.Do (subpath, *i);
|
||||
operation.DoParent (path, m_parent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::list<std::string> names;
|
||||
std::string alternatives = std::string (id, start+1, end-1);
|
||||
std::string::size_type next_pos, cur_pos;
|
||||
next_pos = 0;
|
||||
cur_pos = 0;
|
||||
while (true)
|
||||
{
|
||||
std::string element;
|
||||
next_pos = alternatives.find ("|", cur_pos);
|
||||
if (next_pos == std::string::npos)
|
||||
{
|
||||
element = std::string (alternatives, cur_pos, alternatives.size ());
|
||||
names.push_back (element);
|
||||
break;
|
||||
}
|
||||
element = std::string (alternatives, cur_pos, next_pos);
|
||||
names.push_back (element);
|
||||
cur_pos = next_pos + 1;
|
||||
}
|
||||
for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++)
|
||||
{
|
||||
for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++)
|
||||
{
|
||||
if ((*j)->name == *i)
|
||||
{
|
||||
operation.Do (subpath, *j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
operation.DoParent (path, m_parent);
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
NS_DEBUG ("disconnect path="<<path);
|
||||
class DisconnectOperation : public Operation
|
||||
{
|
||||
public:
|
||||
DisconnectOperation (const CallbackBase &cb)
|
||||
: m_cb (cb)
|
||||
{}
|
||||
virtual void Do (std::string subpath, ResolveItem *item) const
|
||||
{
|
||||
NS_DEBUG ("disconnect from path="<<subpath<<" name="<<item->name);
|
||||
item->Disconnect (subpath, m_cb);
|
||||
}
|
||||
virtual void DoParent (std::string path, Ptr<TraceResolver> parent) const
|
||||
{
|
||||
if (parent != 0)
|
||||
{
|
||||
parent->Disconnect (path, m_cb);
|
||||
}
|
||||
}
|
||||
private:
|
||||
const CallbackBase &m_cb;
|
||||
} operation = DisconnectOperation (cb);
|
||||
DoRecursiveOperation (path, operation);
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolver::CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
|
||||
{
|
||||
NS_DEBUG ("print " << (*i)->name);
|
||||
(*i)->CollectSources (path, context, collection);
|
||||
}
|
||||
if (m_parent != 0)
|
||||
{
|
||||
m_parent->CollectSources (path, context, collection);
|
||||
}
|
||||
}
|
||||
void
|
||||
CompositeTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
|
||||
{
|
||||
NS_DEBUG ("print " << (*i)->name);
|
||||
(*i)->TraceAll (os, context);
|
||||
}
|
||||
if (m_parent != 0)
|
||||
{
|
||||
m_parent->TraceAll (os, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
|
||||
#include "test.h"
|
||||
#include "trace-context-element.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TraceSourceTest : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
enum Sources {
|
||||
DOUBLEA,
|
||||
DOUBLEB,
|
||||
UINT16_T
|
||||
};
|
||||
static uint16_t GetUid (void)
|
||||
{static uint16_t uid = AllocateUid<TraceSourceTest> ("TraceSourceTest"); return uid;}
|
||||
void Print (std::ostream &os)
|
||||
{os << "tracesource=";
|
||||
if (m_sources == DOUBLEA) {os << "doubleA";}
|
||||
else if (m_sources == DOUBLEB) {os << "doubleB";}
|
||||
else if (m_sources == UINT16_T) {os << "uint16_t";}
|
||||
}
|
||||
std::string GetTypeName (void) {return "ns3::TraceSourceTest";}
|
||||
TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {}
|
||||
TraceSourceTest (enum Sources sources) :m_sources (sources) {}
|
||||
bool IsDoubleA (void) const {return m_sources == TraceSourceTest::DOUBLEA;}
|
||||
bool IsDoubleB (void) const {return m_sources == TraceSourceTest::DOUBLEB;}
|
||||
bool IsUint16 (void) const {return m_sources == TraceSourceTest::UINT16_T;}
|
||||
private:
|
||||
enum TraceSourceTest::Sources m_sources;
|
||||
};
|
||||
|
||||
class SubTraceSourceTest : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
enum Sources {
|
||||
INT,
|
||||
};
|
||||
static uint16_t GetUid (void)
|
||||
{static uint16_t uid = AllocateUid<SubTraceSourceTest> ("SubTraceSourceTest"); return uid;}
|
||||
void Print (std::ostream &os)
|
||||
{os << "subtracesource=int";}
|
||||
std::string GetTypeName (void) const {return "ns3::SubTraceSourceTest";}
|
||||
SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {}
|
||||
SubTraceSourceTest (enum Sources sources) : m_sources (sources) {}
|
||||
private:
|
||||
enum Sources m_sources;
|
||||
};
|
||||
|
||||
class CompositeTraceResolverTest : public Test
|
||||
{
|
||||
public:
|
||||
CompositeTraceResolverTest ();
|
||||
virtual ~CompositeTraceResolverTest ();
|
||||
virtual bool RunTests (void);
|
||||
private:
|
||||
void TraceDouble (TraceContext const &context, double v);
|
||||
void TraceInt (TraceContext const &context, int v);
|
||||
Ptr<TraceResolver> CreateSubResolver ();
|
||||
|
||||
|
||||
bool m_gotDoubleA;
|
||||
bool m_gotDoubleB;
|
||||
CallbackTraceSource<int> m_traceInt;
|
||||
bool m_gotInt;
|
||||
};
|
||||
|
||||
CompositeTraceResolverTest::CompositeTraceResolverTest ()
|
||||
: Test ("CompositeTraceResolver")
|
||||
{}
|
||||
CompositeTraceResolverTest::~CompositeTraceResolverTest ()
|
||||
{}
|
||||
void
|
||||
CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
|
||||
{
|
||||
TraceSourceTest source;
|
||||
context.GetElement (source);
|
||||
if (source.IsDoubleA ())
|
||||
{
|
||||
m_gotDoubleA = true;
|
||||
}
|
||||
else if (source.IsDoubleB ())
|
||||
{
|
||||
m_gotDoubleB = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("should not get any other trace source in this sink");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v)
|
||||
{
|
||||
m_gotInt = true;
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
CompositeTraceResolverTest::CreateSubResolver (void)
|
||||
{
|
||||
Ptr<CompositeTraceResolver> subresolver = Create<CompositeTraceResolver> ();
|
||||
subresolver->AddSource ("trace-int", TraceDoc ("test source"), m_traceInt,
|
||||
SubTraceSourceTest (SubTraceSourceTest::INT));
|
||||
return subresolver;
|
||||
}
|
||||
bool
|
||||
CompositeTraceResolverTest::RunTests (void)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
CallbackTraceSource<double> traceDoubleA;
|
||||
CallbackTraceSource<double> traceDoubleB;
|
||||
TraceContext context;
|
||||
|
||||
CompositeTraceResolver resolver;
|
||||
|
||||
resolver.AddSource ("trace-double-a", TraceDoc ("test source"), traceDoubleA,
|
||||
TraceSourceTest (TraceSourceTest::DOUBLEA));
|
||||
resolver.AddSource ("trace-double-b", TraceDoc ("test source"), traceDoubleB,
|
||||
TraceSourceTest (TraceSourceTest::DOUBLEB));
|
||||
|
||||
resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this), TraceContext ());
|
||||
|
||||
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), TraceContext ());
|
||||
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), TraceContext ());
|
||||
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), TraceContext ());
|
||||
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));
|
||||
|
||||
resolver.Connect ("/subresolver/trace-int",
|
||||
MakeCallback (&CompositeTraceResolverTest::TraceInt, this), TraceContext ());
|
||||
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), TraceContext ());
|
||||
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;
|
||||
}
|
||||
|
||||
SVTraceSource<uint16_t> source;
|
||||
|
||||
resolver.AddSource ("uint16_t", TraceDoc ("test source"), source, TraceSourceTest (TraceSourceTest::UINT16_T));
|
||||
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static CompositeTraceResolverTest g_compositeTraceResolverTest;
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
|
||||
#endif /* RUN_SELF_TESTS */
|
||||
233
src/core/composite-trace-resolver.h
Normal file
233
src/core/composite-trace-resolver.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef COMPOSITE_TRACE_RESOLVER_H
|
||||
#define COMPOSITE_TRACE_RESOLVER_H
|
||||
|
||||
#include <vector>
|
||||
#include "callback.h"
|
||||
#include "ptr.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 "array-trace-resolver.h"
|
||||
#include "trace-doc.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief a helper class to aggregate contained TraceResolver and other trace sources.
|
||||
* \ingroup tracing
|
||||
*/
|
||||
class CompositeTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
CompositeTraceResolver ();
|
||||
virtual ~CompositeTraceResolver ();
|
||||
/**
|
||||
* \param name name of trace source
|
||||
* \param doc the documentation associated to this trace source
|
||||
* \param trace a callback trace source
|
||||
* \param context the context associated to this trace source
|
||||
*
|
||||
* Add a callback trace source in this resolver. This trace
|
||||
* source will match the name specified during namespace
|
||||
* resolution. The TraceContext of this trace source will also
|
||||
* be automatically extended to contain the input context.
|
||||
*/
|
||||
template <typename T>
|
||||
void AddSource (std::string name, const TraceDoc &doc,
|
||||
const TraceSource &trace, T const &context);
|
||||
/**
|
||||
* \param name name of trace source
|
||||
* \param doc the documentation associated to this trace source
|
||||
* \param trace a callback trace source
|
||||
*
|
||||
* Add a callback trace source in this resolver. This trace
|
||||
* source will match the name specified during namespace
|
||||
* resolution.
|
||||
*/
|
||||
void AddSource (std::string name,
|
||||
const TraceDoc &doc,
|
||||
const TraceSource &trace);
|
||||
|
||||
/**
|
||||
* \param name the name of the composite element
|
||||
* \param composite the composite object
|
||||
*
|
||||
* The input composite object will be used to resolve a connection
|
||||
* of a disconnection attempt if its name matches the trace path.
|
||||
*
|
||||
*/
|
||||
void AddComposite (std::string name, Ptr<Object> composite);
|
||||
|
||||
/**
|
||||
* \param name the name of the composite element
|
||||
* \param composite the composite object
|
||||
* \param contextElement the context element associated to the composite
|
||||
*
|
||||
* The input composite object will be used to resolve a connection
|
||||
* of a disconnection attempt if its name matches the trace path.
|
||||
* The contextElement will be appended to the TraceContext during connection.
|
||||
*/
|
||||
template <typename T>
|
||||
void AddComposite (std::string name, Ptr<Object> composite, const T &contextElement);
|
||||
|
||||
/**
|
||||
* \param name the name of the array
|
||||
* \param begin an iterator which points to the first element of the array
|
||||
* \param end an iterator which points to the last element of the array
|
||||
* \param index an object which can store the index of an element in the
|
||||
* array. In practice, this object should support a constructor
|
||||
* whose single argument is an array index.
|
||||
*/
|
||||
template <typename ITERATOR, typename INDEX>
|
||||
void AddArray (std::string name,
|
||||
ITERATOR begin, ITERATOR end, INDEX index);
|
||||
|
||||
/**
|
||||
* \param parent the parent trace resolver
|
||||
*
|
||||
* The parent trace resolver is the trace resolver returned by the
|
||||
* GetTraceResolver method of the base class of the caller. It is
|
||||
* used during connection and disconnection to chain up the connect
|
||||
* and disconnect calls to the parent.
|
||||
*/
|
||||
void SetParentResolver (Ptr<TraceResolver> parent);
|
||||
|
||||
|
||||
private:
|
||||
virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
|
||||
virtual void Disconnect (std::string path, CallbackBase const &cb);
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection);
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context);
|
||||
friend class CompositeTraceResolverTest;
|
||||
class ResolveItem
|
||||
{
|
||||
public:
|
||||
virtual ~ResolveItem () {}
|
||||
virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context) = 0;
|
||||
virtual void Disconnect (std::string subpath, const CallbackBase &cb) = 0;
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection) = 0;
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context) = 0;
|
||||
|
||||
std::string name;
|
||||
TraceContext context;
|
||||
};
|
||||
typedef std::vector<ResolveItem *> TraceItems;
|
||||
class Operation
|
||||
{
|
||||
public:
|
||||
virtual ~Operation () {}
|
||||
virtual void Do (std::string subpath, ResolveItem *item) const = 0;
|
||||
virtual void DoParent (std::string path, Ptr<TraceResolver> parent) const = 0;
|
||||
};
|
||||
|
||||
void AddItem (ResolveItem *item);
|
||||
void DoRecursiveOperation (std::string path,
|
||||
const Operation &operation);
|
||||
void DoRecursiveOperationForParent (std::string path,
|
||||
const Operation &operation);
|
||||
void DoAddComposite (std::string name, Ptr<Object> composite, const TraceContext &context);
|
||||
void DoAddSource (std::string name,
|
||||
const TraceDoc &doc,
|
||||
const TraceSource &trace,
|
||||
const TraceContext &context);
|
||||
void Add (std::string name,
|
||||
Callback<Ptr<TraceResolver> > createResolver);
|
||||
|
||||
|
||||
CompositeTraceResolver::TraceItems m_items;
|
||||
Ptr<TraceResolver> m_parent;
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
CompositeTraceResolver::AddSource (std::string name,
|
||||
const TraceDoc &doc,
|
||||
const TraceSource &trace,
|
||||
T const &context)
|
||||
{
|
||||
TraceContext ctx;
|
||||
ctx.AddElement (context);
|
||||
DoAddSource (name, doc, trace, ctx);
|
||||
}
|
||||
|
||||
template <typename ITERATOR, typename INDEX>
|
||||
void
|
||||
CompositeTraceResolver::AddArray (std::string name,
|
||||
ITERATOR begin, ITERATOR end, INDEX index)
|
||||
{
|
||||
class ArrayResolveItem : public ResolveItem
|
||||
{
|
||||
public:
|
||||
virtual void Connect (std::string subpath, const CallbackBase &cb, const TraceContext &context)
|
||||
{array->Connect (subpath, cb, context);}
|
||||
virtual void Disconnect (std::string subpath, const CallbackBase &cb)
|
||||
{array->Disconnect (subpath, cb);}
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
path.append ("/");
|
||||
path.append (this->name);
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
array->CollectSources (path, ctx, collection);
|
||||
}
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
TraceContext ctx = context;
|
||||
ctx.Union (this->context);
|
||||
array->TraceAll (os, ctx);
|
||||
}
|
||||
|
||||
Ptr<ArrayTraceResolver<INDEX> > array;
|
||||
} *item = new ArrayResolveItem ();
|
||||
item->name = name;
|
||||
item->context = TraceContext ();
|
||||
item->array = Create<ArrayTraceResolver<INDEX> > ();
|
||||
item->array->SetIterators (begin, end);
|
||||
AddItem (item);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
CompositeTraceResolver::AddComposite (std::string name, Ptr<Object> composite, const T &contextElement)
|
||||
{
|
||||
TraceContext context;
|
||||
context.AddElement (contextElement);
|
||||
DoAddComposite (name, composite, context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* COMPOSITE_TRACE_RESOLVER_H */
|
||||
@@ -23,11 +23,12 @@
|
||||
#define F_VARIABLE_TRACER_H
|
||||
|
||||
#include "callback-trace-source.h"
|
||||
#include "trace-source.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class FVTraceSourceBase {
|
||||
class FVTraceSourceBase : public TraceSource {
|
||||
public:
|
||||
typedef CallbackTraceSource<double, double> ChangeNotifyCallback;
|
||||
|
||||
@@ -39,12 +40,15 @@ public:
|
||||
|
||||
~FVTraceSourceBase () {}
|
||||
|
||||
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
|
||||
virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) {
|
||||
m_callback.AddCallback (callback, context);
|
||||
}
|
||||
void RemoveCallback (CallbackBase const & callback) {
|
||||
virtual void RemoveCallback (CallbackBase const & callback) {
|
||||
m_callback.RemoveCallback (callback);
|
||||
}
|
||||
virtual void ConnectPrinter (std::ostream &os, const TraceContext &context) {
|
||||
m_callback.ConnectPrinter (os, context);
|
||||
}
|
||||
protected:
|
||||
void notify (double oldVal, double newVal) {
|
||||
if (oldVal != newVal)
|
||||
@@ -22,8 +22,12 @@
|
||||
#include "assert.h"
|
||||
#include "singleton.h"
|
||||
#include "uid-manager.h"
|
||||
#include "trace-resolver.h"
|
||||
#include "debug.h"
|
||||
#include <vector>
|
||||
|
||||
NS_DEBUG_COMPONENT_DEFINE ("Object");
|
||||
|
||||
namespace {
|
||||
|
||||
class IidManager : public ns3::UidManager
|
||||
@@ -34,6 +38,7 @@ class IidTree
|
||||
public:
|
||||
void SetParent (uint16_t child, const uint16_t *parent);
|
||||
uint16_t LookupParent (uint16_t child);
|
||||
|
||||
private:
|
||||
std::vector<const uint16_t *> m_parents;
|
||||
};
|
||||
@@ -55,6 +60,68 @@ IidTree::LookupParent (uint16_t child)
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class InterfaceIdTraceResolver : public TraceResolver
|
||||
{
|
||||
public:
|
||||
InterfaceIdTraceResolver (Ptr<const Object> aggregate);
|
||||
virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
|
||||
virtual void Disconnect (std::string path, CallbackBase const &cb);
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection);
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context);
|
||||
private:
|
||||
Ptr<const Object> ParseForInterface (std::string path);
|
||||
Ptr<const Object> m_aggregate;
|
||||
};
|
||||
|
||||
InterfaceIdTraceResolver::InterfaceIdTraceResolver (Ptr<const Object> aggregate)
|
||||
: m_aggregate (aggregate)
|
||||
{}
|
||||
Ptr<const Object>
|
||||
InterfaceIdTraceResolver::ParseForInterface (std::string path)
|
||||
{
|
||||
std::string element = GetElement (path);
|
||||
std::string::size_type dollar_pos = element.find ("$");
|
||||
if (dollar_pos != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
std::string interfaceName = element.substr (1, std::string::npos);
|
||||
InterfaceId interfaceId = InterfaceId::LookupByName (interfaceName);
|
||||
Ptr<Object> interface = m_aggregate->QueryInterface<Object> (interfaceId);
|
||||
return interface;
|
||||
}
|
||||
void
|
||||
InterfaceIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
|
||||
{
|
||||
Ptr<const Object> interface = ParseForInterface (path);
|
||||
if (interface != 0)
|
||||
{
|
||||
interface->GetTraceResolver ()->Connect (GetSubpath (path), cb, context);
|
||||
}
|
||||
}
|
||||
void
|
||||
InterfaceIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
|
||||
{
|
||||
Ptr<const Object> interface = ParseForInterface (path);
|
||||
if (interface != 0)
|
||||
{
|
||||
interface->TraceDisconnect (GetSubpath (path), cb);
|
||||
}
|
||||
}
|
||||
void
|
||||
InterfaceIdTraceResolver::CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection)
|
||||
{
|
||||
m_aggregate->DoCollectSources (path, context, collection);
|
||||
}
|
||||
void
|
||||
InterfaceIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
|
||||
{
|
||||
m_aggregate->DoTraceAll (os, context);
|
||||
}
|
||||
|
||||
|
||||
InterfaceId::InterfaceId (uint16_t iid)
|
||||
: m_iid (iid)
|
||||
{}
|
||||
@@ -72,6 +139,12 @@ InterfaceId::LookupParent (InterfaceId iid)
|
||||
{
|
||||
return Singleton<IidTree>::Get ()->LookupParent (iid.m_iid);
|
||||
}
|
||||
std::string
|
||||
InterfaceId::GetName (void) const
|
||||
{
|
||||
std::string name = Singleton<IidManager>::Get ()->LookupByUid (m_iid);
|
||||
return name;
|
||||
}
|
||||
|
||||
bool operator == (const InterfaceId &a, const InterfaceId &b)
|
||||
{
|
||||
@@ -109,6 +182,7 @@ Object::Object ()
|
||||
: m_count (1),
|
||||
m_iid (Object::iid),
|
||||
m_disposed (false),
|
||||
m_collecting (false),
|
||||
m_next (this)
|
||||
{}
|
||||
Object::~Object ()
|
||||
@@ -163,6 +237,17 @@ Object::AddInterface (Ptr<Object> o)
|
||||
NS_ASSERT (o->Check ());
|
||||
}
|
||||
|
||||
void
|
||||
Object::TraceConnect (std::string path, const CallbackBase &cb) const
|
||||
{
|
||||
GetTraceResolver ()->Connect (path, cb, TraceContext ());
|
||||
}
|
||||
void
|
||||
Object::TraceDisconnect (std::string path, const CallbackBase &cb) const
|
||||
{
|
||||
GetTraceResolver ()->Disconnect (path, cb);
|
||||
}
|
||||
|
||||
void
|
||||
Object::SetInterfaceId (InterfaceId iid)
|
||||
{
|
||||
@@ -176,6 +261,14 @@ Object::DoDispose (void)
|
||||
NS_ASSERT (!m_disposed);
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
Object::GetTraceResolver (void) const
|
||||
{
|
||||
Ptr<InterfaceIdTraceResolver> resolver =
|
||||
Create<InterfaceIdTraceResolver> (this);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
bool
|
||||
Object::Check (void) const
|
||||
{
|
||||
@@ -209,12 +302,77 @@ Object::MaybeDelete (void) const
|
||||
} while (current != end);
|
||||
}
|
||||
|
||||
void
|
||||
Object::DoCollectSources (std::string path, const TraceContext &context,
|
||||
TraceResolver::SourceCollection *collection) const
|
||||
{
|
||||
const Object *current;
|
||||
current = this;
|
||||
do {
|
||||
if (current->m_collecting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
current = current->m_next;
|
||||
} while (current != this);
|
||||
|
||||
m_collecting = true;
|
||||
|
||||
current = this->m_next;
|
||||
while (current != this)
|
||||
{
|
||||
NS_ASSERT (current != 0);
|
||||
NS_DEBUG ("collect current=" << current);
|
||||
InterfaceId cur = current->m_iid;
|
||||
while (cur != Object::iid)
|
||||
{
|
||||
std::string name = cur.GetName ();
|
||||
std::string fullpath = path;
|
||||
fullpath.append ("/$");
|
||||
fullpath.append (name);
|
||||
NS_DEBUG ("collect: " << fullpath);
|
||||
current->GetTraceResolver ()->CollectSources (fullpath, context, collection);
|
||||
cur = InterfaceId::LookupParent (cur);
|
||||
}
|
||||
current = current->m_next;
|
||||
}
|
||||
|
||||
m_collecting = false;
|
||||
}
|
||||
void
|
||||
Object::DoTraceAll (std::ostream &os, const TraceContext &context) const
|
||||
{
|
||||
const Object *current;
|
||||
current = this;
|
||||
do {
|
||||
if (current->m_collecting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
current = current->m_next;
|
||||
} while (current != this);
|
||||
|
||||
m_collecting = true;
|
||||
|
||||
current = this->m_next;
|
||||
while (current != this)
|
||||
{
|
||||
NS_ASSERT (current != 0);
|
||||
current->GetTraceResolver ()->TraceAll (os, context);
|
||||
current = current->m_next;
|
||||
}
|
||||
|
||||
m_collecting = false;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
|
||||
#include "test.h"
|
||||
#include "sv-trace-source.h"
|
||||
#include "composite-trace-resolver.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -226,7 +384,18 @@ public:
|
||||
{
|
||||
SetInterfaceId (BaseA::iid);
|
||||
}
|
||||
void BaseGenerateTrace (int16_t v)
|
||||
{ m_source = v; }
|
||||
virtual void Dispose (void) {}
|
||||
virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
|
||||
{
|
||||
ns3::Ptr<ns3::CompositeTraceResolver> resolver =
|
||||
ns3::Create<ns3::CompositeTraceResolver> ();
|
||||
resolver->AddSource ("basea-x", ns3::TraceDoc ("test source"), m_source);
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
ns3::SVTraceSource<int16_t> m_source;
|
||||
};
|
||||
|
||||
class DerivedA : public BaseA
|
||||
@@ -237,9 +406,20 @@ public:
|
||||
{
|
||||
SetInterfaceId (DerivedA::iid);
|
||||
}
|
||||
void DerivedGenerateTrace (int16_t v)
|
||||
{ m_sourceDerived = v; }
|
||||
virtual void Dispose (void) {
|
||||
BaseA::Dispose ();
|
||||
}
|
||||
virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
|
||||
{
|
||||
ns3::Ptr<ns3::CompositeTraceResolver> resolver =
|
||||
ns3::Create<ns3::CompositeTraceResolver> ();
|
||||
resolver->AddSource ("deriveda-x", ns3::TraceDoc ("test source"), m_sourceDerived);
|
||||
resolver->SetParentResolver (BaseA::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
ns3::SVTraceSource<int16_t> m_sourceDerived;
|
||||
};
|
||||
|
||||
const ns3::InterfaceId BaseA::iid =
|
||||
@@ -255,7 +435,18 @@ public:
|
||||
{
|
||||
SetInterfaceId (BaseB::iid);
|
||||
}
|
||||
void BaseGenerateTrace (int16_t v)
|
||||
{ m_source = v; }
|
||||
virtual void Dispose (void) {}
|
||||
virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
|
||||
{
|
||||
ns3::Ptr<ns3::CompositeTraceResolver> resolver =
|
||||
ns3::Create<ns3::CompositeTraceResolver> ();
|
||||
resolver->AddSource ("baseb-x", ns3::TraceDoc ("test source"), m_source);
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
ns3::SVTraceSource<int16_t> m_source;
|
||||
};
|
||||
|
||||
class DerivedB : public BaseB
|
||||
@@ -266,9 +457,20 @@ public:
|
||||
{
|
||||
SetInterfaceId (DerivedB::iid);
|
||||
}
|
||||
void DerivedGenerateTrace (int16_t v)
|
||||
{ m_sourceDerived = v; }
|
||||
virtual void Dispose (void) {
|
||||
BaseB::Dispose ();
|
||||
}
|
||||
virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
|
||||
{
|
||||
ns3::Ptr<ns3::CompositeTraceResolver> resolver =
|
||||
ns3::Create<ns3::CompositeTraceResolver> ();
|
||||
resolver->AddSource ("derivedb-x", ns3::TraceDoc ("test source"), m_sourceDerived);
|
||||
resolver->SetParentResolver (BaseB::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
ns3::SVTraceSource<int16_t> m_sourceDerived;
|
||||
};
|
||||
|
||||
const ns3::InterfaceId BaseB::iid =
|
||||
@@ -285,120 +487,82 @@ class ObjectTest : public Test
|
||||
public:
|
||||
ObjectTest ();
|
||||
virtual bool RunTests (void);
|
||||
private:
|
||||
void BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
|
||||
void DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
|
||||
void BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
|
||||
void DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
|
||||
|
||||
bool m_baseATrace;
|
||||
bool m_derivedATrace;
|
||||
bool m_baseBTrace;
|
||||
bool m_derivedBTrace;
|
||||
};
|
||||
|
||||
ObjectTest::ObjectTest ()
|
||||
: Test ("Object")
|
||||
{}
|
||||
void
|
||||
ObjectTest::BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
|
||||
{
|
||||
m_baseATrace = true;
|
||||
}
|
||||
void
|
||||
ObjectTest::DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
|
||||
{
|
||||
m_derivedATrace = true;
|
||||
}
|
||||
void
|
||||
ObjectTest::BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
|
||||
{
|
||||
m_baseBTrace = true;
|
||||
}
|
||||
void
|
||||
ObjectTest::DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
|
||||
{
|
||||
m_derivedBTrace = true;
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectTest::RunTests (void)
|
||||
{
|
||||
bool ok = true;
|
||||
bool result = true;
|
||||
|
||||
Ptr<BaseA> baseA = Create<BaseA> ();
|
||||
if (baseA->QueryInterface<BaseA> (BaseA::iid) != baseA)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<BaseA> (DerivedA::iid) != 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<DerivedA> (DerivedA::iid) != 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (BaseA::iid), baseA);
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (DerivedA::iid), 0);
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedA> (DerivedA::iid), 0);
|
||||
baseA = Create<DerivedA> (10);
|
||||
if (baseA->QueryInterface<BaseA> (BaseA::iid) != baseA)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<BaseA> (DerivedA::iid) != baseA)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<DerivedA> (DerivedA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (BaseA::iid), baseA);
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (DerivedA::iid), baseA);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<DerivedA> (DerivedA::iid), 0);
|
||||
|
||||
baseA = Create<BaseA> ();
|
||||
Ptr<BaseB> baseB = Create<BaseB> ();
|
||||
Ptr<BaseB> baseBCopy = baseB;
|
||||
baseA->AddInterface (baseB);
|
||||
if (baseA->QueryInterface<BaseA> (BaseA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<DerivedA> (DerivedA::iid) != 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<BaseB> (BaseB::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<DerivedB> (DerivedB::iid) != 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<BaseB> (BaseB::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<DerivedB> (DerivedB::iid) != 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<BaseA> (BaseA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<DerivedA> (DerivedA::iid) != 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseBCopy->QueryInterface<BaseA> (BaseA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<BaseA> (BaseA::iid), 0);
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedA> (DerivedA::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<BaseB> (BaseB::iid), 0);
|
||||
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedB> (DerivedB::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseB> (BaseB::iid), 0);
|
||||
NS_TEST_ASSERT_EQUAL (baseB->QueryInterface<DerivedB> (DerivedB::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseA> (BaseA::iid), 0);
|
||||
NS_TEST_ASSERT_EQUAL (baseB->QueryInterface<DerivedA> (DerivedA::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<BaseA> (BaseA::iid), 0);
|
||||
|
||||
baseA = Create<DerivedA> (1);
|
||||
baseB = Create<DerivedB> (1);
|
||||
baseBCopy = baseB;
|
||||
baseA->AddInterface (baseB);
|
||||
if (baseA->QueryInterface<DerivedB> (DerivedB::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseA->QueryInterface<BaseB> (BaseB::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<DerivedA> (DerivedA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<BaseA> (BaseA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseBCopy->QueryInterface<DerivedA> (DerivedA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseBCopy->QueryInterface<BaseA> (BaseA::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<DerivedB> (DerivedB::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
if (baseB->QueryInterface<BaseB> (BaseB::iid) == 0)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<DerivedB> (DerivedB::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<BaseB> (BaseB::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<DerivedA> (DerivedA::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseA> (BaseA::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<DerivedA> (DerivedA::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<BaseA> (BaseA::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<DerivedB> (DerivedB::iid), 0);
|
||||
NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface<BaseB> (BaseB::iid), 0)
|
||||
|
||||
baseA = Create<BaseA> ();
|
||||
baseB = Create<BaseB> ();
|
||||
@@ -406,7 +570,76 @@ ObjectTest::RunTests (void)
|
||||
baseA = 0;
|
||||
baseA = baseB->QueryInterface<BaseA> (BaseA::iid);
|
||||
|
||||
return ok;
|
||||
baseA = Create<BaseA> ();
|
||||
baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
m_baseATrace = false;
|
||||
baseA->BaseGenerateTrace (1);
|
||||
NS_TEST_ASSERT (m_baseATrace);
|
||||
baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
|
||||
baseB = Create<BaseB> ();
|
||||
baseB->TraceConnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
|
||||
m_baseBTrace = false;
|
||||
baseB->BaseGenerateTrace (2);
|
||||
NS_TEST_ASSERT (m_baseBTrace);
|
||||
baseB->TraceDisconnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
|
||||
|
||||
baseA->AddInterface (baseB);
|
||||
|
||||
baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
m_baseATrace = false;
|
||||
baseA->BaseGenerateTrace (3);
|
||||
NS_TEST_ASSERT (m_baseATrace);
|
||||
baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
|
||||
baseA->TraceConnect ("/$BaseB/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
|
||||
m_baseBTrace = false;
|
||||
baseB->BaseGenerateTrace (4);
|
||||
NS_TEST_ASSERT (m_baseBTrace);
|
||||
baseA->TraceDisconnect ("/$BaseB/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
|
||||
m_baseBTrace = false;
|
||||
baseB->BaseGenerateTrace (5);
|
||||
NS_TEST_ASSERT (!m_baseBTrace);
|
||||
|
||||
baseB->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
m_baseATrace = false;
|
||||
baseA->BaseGenerateTrace (6);
|
||||
NS_TEST_ASSERT (m_baseATrace);
|
||||
baseB->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
|
||||
baseA->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
m_baseATrace = false;
|
||||
baseA->BaseGenerateTrace (7);
|
||||
NS_TEST_ASSERT (m_baseATrace);
|
||||
baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
|
||||
Ptr<DerivedA> derivedA;
|
||||
derivedA = Create<DerivedA> (1);
|
||||
baseB = Create<BaseB> ();
|
||||
derivedA->AddInterface (baseB);
|
||||
baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
|
||||
baseB->TraceConnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
m_derivedATrace = false;
|
||||
m_baseATrace = false;
|
||||
derivedA->DerivedGenerateTrace (8);
|
||||
derivedA->BaseGenerateTrace (9);
|
||||
NS_TEST_ASSERT (m_derivedATrace);
|
||||
NS_TEST_ASSERT (m_baseATrace);
|
||||
baseB->TraceDisconnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
baseB->TraceDisconnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
|
||||
baseB->TraceConnect ("/$DerivedA/*", MakeCallback (&ObjectTest::DerivedATrace, this));
|
||||
m_derivedATrace = false;
|
||||
derivedA->DerivedGenerateTrace (10);
|
||||
NS_TEST_ASSERT (m_derivedATrace);
|
||||
// here, we have connected the derived trace sink to all
|
||||
// trace sources, including the base trace source.
|
||||
m_derivedATrace = false;
|
||||
derivedA->BaseGenerateTrace (11);
|
||||
NS_TEST_ASSERT (m_derivedATrace);
|
||||
baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ObjectTest g_interfaceObjectTests;
|
||||
|
||||
@@ -24,9 +24,13 @@
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "ptr.h"
|
||||
#include "trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TraceContext;
|
||||
class CallbackBase;
|
||||
|
||||
/**
|
||||
* \brief a unique identifier for an interface.
|
||||
*
|
||||
@@ -56,6 +60,11 @@ public:
|
||||
* id is not a valid interface id.
|
||||
*/
|
||||
static InterfaceId LookupParent (InterfaceId iid);
|
||||
|
||||
/**
|
||||
* \returns the name of this interface.
|
||||
*/
|
||||
std::string GetName (void) const;
|
||||
~InterfaceId ();
|
||||
private:
|
||||
InterfaceId (uint16_t iid);
|
||||
@@ -131,6 +140,30 @@ public:
|
||||
* on one to get the other, and vice-versa.
|
||||
*/
|
||||
void AddInterface (Ptr<Object> other);
|
||||
|
||||
/**
|
||||
* \param path the path to match for the callback
|
||||
* \param cb callback to connect
|
||||
*
|
||||
* Connect the input callback to all trace sources which
|
||||
* match the input path.
|
||||
*
|
||||
*/
|
||||
void TraceConnect (std::string path, const CallbackBase &cb) const;
|
||||
/**
|
||||
* \param path the path to match for the callback
|
||||
* \param cb callback to disconnect
|
||||
*
|
||||
* Disconnect the input callback from all trace sources which
|
||||
* match the input path.
|
||||
*/
|
||||
void TraceDisconnect (std::string path, const CallbackBase &cb) const;
|
||||
/**
|
||||
* \returns the trace resolver associated to this object.
|
||||
*
|
||||
* This method should be rarely called by users.
|
||||
*/
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
protected:
|
||||
/**
|
||||
* \param iid an InterfaceId
|
||||
@@ -147,12 +180,17 @@ protected:
|
||||
*/
|
||||
virtual void DoDispose (void);
|
||||
private:
|
||||
friend class InterfaceIdTraceResolver;
|
||||
Ptr<Object> DoQueryInterface (InterfaceId iid) const;
|
||||
void DoCollectSources (std::string path, const TraceContext &context,
|
||||
TraceResolver::SourceCollection *collection) const;
|
||||
void DoTraceAll (std::ostream &os, const TraceContext &context) const;
|
||||
bool Check (void) const;
|
||||
void MaybeDelete (void) const;
|
||||
mutable uint32_t m_count;
|
||||
InterfaceId m_iid;
|
||||
bool m_disposed;
|
||||
mutable bool m_collecting;
|
||||
Object *m_next;
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "random-variable-default-value.h"
|
||||
#include "ns3/debug.h"
|
||||
#include "debug.h"
|
||||
|
||||
NS_DEBUG_COMPONENT_DEFINE ("RandomVariableDefaultValue");
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "stream-tracer.h"
|
||||
#include "ns3/test.h"
|
||||
#include "test.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
@@ -23,11 +23,12 @@
|
||||
#define SV_TRACE_SOURCE_H
|
||||
|
||||
#include "callback-trace-source.h"
|
||||
#include "trace-source.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class SVTraceSourceBase {
|
||||
class SVTraceSourceBase : public TraceSource {
|
||||
public:
|
||||
typedef CallbackTraceSource<int64_t, int64_t> ChangeNotifyCallback;
|
||||
|
||||
@@ -37,14 +38,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SVTraceSourceBase () {}
|
||||
virtual ~SVTraceSourceBase () {}
|
||||
|
||||
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
|
||||
virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) {
|
||||
m_callback.AddCallback (callback, context);
|
||||
}
|
||||
void RemoveCallback (CallbackBase const & callback) {
|
||||
virtual void RemoveCallback (CallbackBase const & callback) {
|
||||
m_callback.RemoveCallback (callback);
|
||||
}
|
||||
virtual void ConnectPrinter (std::ostream &os, const TraceContext &context) {
|
||||
m_callback.ConnectPrinter (os, context);
|
||||
}
|
||||
protected:
|
||||
void Notify (int64_t oldVal, int64_t newVal) {
|
||||
if (oldVal != newVal)
|
||||
@@ -62,7 +66,7 @@ class UVTraceSource;
|
||||
|
||||
/**
|
||||
* \brief trace variables of type "signed integer"
|
||||
* \ingroup lowleveltracing
|
||||
* \ingroup tracing
|
||||
*
|
||||
* This template class implements a POD type: it
|
||||
* behaves like any other variable of type "signed integer"
|
||||
@@ -74,7 +78,7 @@ class UVTraceSource;
|
||||
* ns3::UVTraceSource<int32_t> :
|
||||
\code
|
||||
#include <stdint.h>
|
||||
#include "ns3/sv-trace-source.h"
|
||||
#include "sv-trace-source.h"
|
||||
|
||||
ns3::SVTraceSource<uint16_t> var;
|
||||
\endcode
|
||||
@@ -118,6 +118,23 @@ private:
|
||||
<< ", got " << (got) << std::endl; \
|
||||
result = false; \
|
||||
}
|
||||
/**
|
||||
* Convenience macro to check that a value returned by a test is what
|
||||
* is expected. Note: this macro assumes a 'bool result = true'
|
||||
* declaration exists in the test function body, and that the function
|
||||
* returns that value.
|
||||
*
|
||||
* \param got value obtained from the test
|
||||
* \param expected value that the test is expected to return
|
||||
*/
|
||||
#define NS_TEST_ASSERT_UNEQUAL(got, expected) \
|
||||
if ((got) == (expected)) \
|
||||
{ \
|
||||
Failure () << __FILE__ << ":" <<__LINE__ \
|
||||
<< ": did not want " << (expected) \
|
||||
<< ", got " << (got) << std::endl; \
|
||||
result = false; \
|
||||
}
|
||||
/**
|
||||
* Convenience macro to check an assertion is held during an unit
|
||||
* test. Note: this macro assumes a 'bool result = true' declaration
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
std::string
|
||||
ElementRegistry::GetTypeName (uint16_t uid)
|
||||
{
|
||||
InfoVector *vec = GetInfoVector ();
|
||||
struct Info info = (*vec)[uid - 1];
|
||||
return info.getTypeName ();
|
||||
}
|
||||
uint32_t
|
||||
ElementRegistry::GetSize (uint16_t uid)
|
||||
{
|
||||
@@ -37,6 +37,8 @@ namespace ns3 {
|
||||
* This method takes a c++ output stream and argument and is
|
||||
* expected to write an ascii string describing its content
|
||||
* in this output stream.
|
||||
* - a public GetTypeName method which returns the fully-qualified
|
||||
* c++ type name of this subclass as a string.
|
||||
*
|
||||
* A typical subclass should look like this:
|
||||
* \code
|
||||
@@ -48,6 +50,7 @@ namespace ns3 {
|
||||
* MyContext ();
|
||||
* ~MyContext ();
|
||||
* void Print (std::ostream &os) const;
|
||||
* std::string GetTypeName (void) const;
|
||||
*
|
||||
* // the user-specific API to manipulate the context.
|
||||
* void SetData (uint8_t data);
|
||||
@@ -71,6 +74,12 @@ namespace ns3 {
|
||||
* {
|
||||
* os << "mycontext=" << (uint32_t) m_myContextData;
|
||||
* }
|
||||
* std::string
|
||||
* MyContext::GetTypeName (void) const
|
||||
* {
|
||||
* // return a fully-qualified c++ type name
|
||||
* return "MyContext";
|
||||
* }
|
||||
* void
|
||||
* MyContext::SetData (uint8_t data)
|
||||
* {
|
||||
@@ -115,19 +124,24 @@ public:
|
||||
|
||||
static uint32_t GetSize (uint16_t uid);
|
||||
static void Print (uint16_t uid, uint8_t *instance, std::ostream &os);
|
||||
static std::string GetTypeName (uint16_t uid);
|
||||
static void Destroy (uint16_t uid, uint8_t *instance);
|
||||
private:
|
||||
typedef std::string (*GetTypeNameCb) (void);
|
||||
typedef void (*PrintCb) (uint8_t *instance, std::ostream &os);
|
||||
typedef void (*DestroyCb) (uint8_t *instance);
|
||||
struct Info {
|
||||
uint32_t size;
|
||||
std::string uidString;
|
||||
GetTypeNameCb getTypeName;
|
||||
PrintCb print;
|
||||
DestroyCb destroy;
|
||||
};
|
||||
typedef std::vector<struct Info> InfoVector;
|
||||
static InfoVector *GetInfoVector (void);
|
||||
template <typename T>
|
||||
static std::string DoGetTypeName (void);
|
||||
template <typename T>
|
||||
static void DoPrint (uint8_t *instance, std::ostream &os);
|
||||
template <typename T>
|
||||
static void DoDestroy (uint8_t *instance);
|
||||
@@ -143,6 +157,13 @@ ElementRegistry::DoPrint (uint8_t *instance, std::ostream &os)
|
||||
obj.Print (os);
|
||||
}
|
||||
template <typename T>
|
||||
std::string
|
||||
ElementRegistry::DoGetTypeName (void)
|
||||
{
|
||||
static T obj;
|
||||
return obj.GetTypeName ();
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
ElementRegistry::DoDestroy (uint8_t *instance)
|
||||
{
|
||||
@@ -169,6 +190,7 @@ ElementRegistry::AllocateUid (std::string name)
|
||||
struct Info info;
|
||||
info.size = sizeof (T);
|
||||
info.uidString = name;
|
||||
info.getTypeName = &ElementRegistry::DoGetTypeName<T>;
|
||||
info.print = &ElementRegistry::DoPrint<T>;
|
||||
info.destroy = &ElementRegistry::DoDestroy<T>;
|
||||
vec->push_back (info);
|
||||
@@ -20,10 +20,56 @@
|
||||
*/
|
||||
#include "trace-context.h"
|
||||
#include "trace-context-element.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "assert.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
TraceContext::Iterator::Iterator ()
|
||||
: m_buffer (0),
|
||||
m_size (0),
|
||||
m_current (0)
|
||||
{}
|
||||
TraceContext::Iterator::Iterator (uint8_t *buffer, uint16_t size)
|
||||
: m_buffer (buffer),
|
||||
m_size (size),
|
||||
m_current (0)
|
||||
{
|
||||
m_uid = m_buffer[m_current];
|
||||
}
|
||||
bool
|
||||
TraceContext::Iterator::IsLast (void) const
|
||||
{
|
||||
if (m_buffer == 0 || m_uid == 0 || m_current >= m_size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void
|
||||
TraceContext::Iterator::Next (void)
|
||||
{
|
||||
if (m_buffer == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_uid == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t size = ElementRegistry::GetSize (m_uid);
|
||||
m_current += 1 + size;
|
||||
}
|
||||
m_uid = m_buffer[m_current];
|
||||
}
|
||||
std::string
|
||||
TraceContext::Iterator::Get (void) const
|
||||
{
|
||||
std::string name = ElementRegistry::GetTypeName (m_uid);
|
||||
return name;
|
||||
}
|
||||
|
||||
TraceContext::TraceContext ()
|
||||
: m_data (0)
|
||||
{}
|
||||
@@ -68,7 +114,7 @@ TraceContext::~TraceContext ()
|
||||
}
|
||||
|
||||
void
|
||||
TraceContext::Add (TraceContext const &o)
|
||||
TraceContext::Union (TraceContext const &o)
|
||||
{
|
||||
if (o.m_data == 0)
|
||||
{
|
||||
@@ -230,10 +276,93 @@ TraceContext::Print (std::ostream &os) const
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
TraceContext::Iterator
|
||||
TraceContext::Begin (void) const
|
||||
{
|
||||
if (m_data == 0)
|
||||
{
|
||||
return Iterator ();
|
||||
}
|
||||
return Iterator (m_data->data, m_data->size);
|
||||
}
|
||||
|
||||
void
|
||||
TraceContext::PrintAvailable (std::ostream &os, std::string separator) const
|
||||
{
|
||||
if (m_data == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint8_t currentUid;
|
||||
uint16_t i = 0;
|
||||
do {
|
||||
currentUid = m_data->data[i];
|
||||
uint8_t size = ElementRegistry::GetSize (currentUid);
|
||||
os << ElementRegistry::GetTypeName (currentUid);
|
||||
i += 1 + size;
|
||||
if (i < m_data->size && currentUid != 0)
|
||||
{
|
||||
os << separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
bool
|
||||
TraceContext::IsSimilar (const TraceContext &o) const
|
||||
{
|
||||
if (m_data == 0 && o.m_data == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ((m_data != 0 && o.m_data == 0) ||
|
||||
(m_data == 0 && o.m_data != 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint8_t myCurrentUid;
|
||||
uint16_t myI = 0;
|
||||
uint8_t otherCurrentUid;
|
||||
uint16_t otherI = 0;
|
||||
|
||||
myCurrentUid = m_data->data[myI];
|
||||
otherCurrentUid = o.m_data->data[otherI];
|
||||
|
||||
while (myCurrentUid == otherCurrentUid &&
|
||||
myCurrentUid != 0 &&
|
||||
otherCurrentUid != 0 &&
|
||||
myI < m_data->size &&
|
||||
otherI < o.m_data->size)
|
||||
{
|
||||
uint8_t mySize = ElementRegistry::GetSize (myCurrentUid);
|
||||
uint8_t otherSize = ElementRegistry::GetSize (otherCurrentUid);
|
||||
myI += 1 + mySize;
|
||||
otherI += 1 + otherSize;
|
||||
myCurrentUid = m_data->data[myI];
|
||||
otherCurrentUid = o.m_data->data[otherI];
|
||||
}
|
||||
if (myCurrentUid == 0 && otherCurrentUid == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const TraceContext &context)
|
||||
{
|
||||
context.Print (os);
|
||||
return os;
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "test.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace ns3 {
|
||||
@@ -242,8 +371,8 @@ template <int N>
|
||||
class Ctx : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
static uint16_t GetUid (void) {static uint16_t uid = AllocateUid<Ctx<N> > (GetName ()); return uid;}
|
||||
static std::string GetName (void) {std::ostringstream oss; oss << "Ctx" << N; return oss.str ();}
|
||||
static uint16_t GetUid (void) {static uint16_t uid = AllocateUid<Ctx<N> > (GetTypeName ()); return uid;}
|
||||
static std::string GetTypeName (void) {std::ostringstream oss; oss << "Ctx" << N; return oss.str ();}
|
||||
Ctx () : m_v (0) {}
|
||||
Ctx (int v) : m_v (v) {}
|
||||
void Print (std::ostream &os) {os << N;}
|
||||
@@ -278,31 +407,31 @@ TraceContextTest::RunTests (void)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
ctx.Add (v0);
|
||||
ctx.Add (v0);
|
||||
ctx.AddElement (v0);
|
||||
ctx.AddElement (v0);
|
||||
if (ctx.SafeAdd (v01))
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
ctx.Get (v0);
|
||||
ctx.Add (v1);
|
||||
ctx.Get (v1);
|
||||
ctx.Get (v0);
|
||||
ctx.Get (v1);
|
||||
ctx.GetElement (v0);
|
||||
ctx.AddElement (v1);
|
||||
ctx.GetElement (v1);
|
||||
ctx.GetElement (v0);
|
||||
ctx.GetElement (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);
|
||||
ctx.GetElement (v0);
|
||||
ctx.GetElement (v1);
|
||||
copy.GetElement (v0);
|
||||
copy.GetElement (v1);
|
||||
copy.AddElement (v2);
|
||||
copy.GetElement (v0);
|
||||
copy.GetElement (v1);
|
||||
copy.GetElement (v2);
|
||||
ctx.AddElement (v3);
|
||||
ctx.GetElement (v0);
|
||||
ctx.GetElement (v1);
|
||||
ctx.GetElement (v3);
|
||||
|
||||
if (ctx.SafeGet (v2))
|
||||
{
|
||||
@@ -312,14 +441,14 @@ TraceContextTest::RunTests (void)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
ctx.Add (copy);
|
||||
ctx.Get (v2);
|
||||
ctx.Union (copy);
|
||||
ctx.GetElement (v2);
|
||||
if (copy.SafeGet (v3))
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
copy.Add (ctx);
|
||||
copy.Get (v3);
|
||||
copy.Union (ctx);
|
||||
copy.GetElement (v3);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -23,26 +23,28 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "ns3/fatal-error.h"
|
||||
#include "fatal-error.h"
|
||||
#include "trace-context-element.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Provide context to trace sources
|
||||
* \ingroup lowleveltracing
|
||||
* \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
|
||||
* TraceContextElement. Trace sinks can lookup these contexts
|
||||
* from this list with the ns3::TraceContext::Get method.
|
||||
* They can also ask the TraceContext for the list of
|
||||
* TraceContextElements it contains with the PrintAvailable 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.
|
||||
* to ns3::TraceContext::AddElement or ns3::TraceContext::Union
|
||||
* will trigger a costly memory reallocation if needed.
|
||||
*/
|
||||
class TraceContext
|
||||
{
|
||||
@@ -54,32 +56,73 @@ public:
|
||||
|
||||
/**
|
||||
* \param context add context to list of trace contexts.
|
||||
*
|
||||
* A copy of the input context is appended at the end of the list
|
||||
* stored in this TraceContext.
|
||||
*/
|
||||
template <typename T>
|
||||
void Add (T const &context);
|
||||
void AddElement (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
|
||||
* ns3::CallbackTraceSource 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);
|
||||
void Union (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.
|
||||
* \returns true if the requested trace context element was found
|
||||
* in this TraceContext, false otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
void Get (T &context) const;
|
||||
bool GetElement (T &context) const;
|
||||
|
||||
/**
|
||||
* \param os a c++ STL output stream
|
||||
*
|
||||
* Iterate over the list of TraceContextElement stored in this
|
||||
* TraceContext and invoke each of their Print method.
|
||||
*/
|
||||
void Print (std::ostream &os) const;
|
||||
/**
|
||||
* \param os a c++ STL output stream
|
||||
* \param separator the separator inserted between each TraceContextElement typename.
|
||||
*
|
||||
* Print the typename of each TraceContextElement stored in this TraceContext.
|
||||
*/
|
||||
void PrintAvailable (std::ostream &os, std::string separator) const;
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
void Next (void);
|
||||
bool IsLast (void) const;
|
||||
std::string Get (void) const;
|
||||
private:
|
||||
friend class TraceContext;
|
||||
Iterator ();
|
||||
Iterator (uint8_t *buffer, uint16_t index);
|
||||
uint8_t *m_buffer;
|
||||
uint16_t m_size;
|
||||
uint16_t m_current;
|
||||
uint8_t m_uid;
|
||||
};
|
||||
Iterator Begin (void) const;
|
||||
/**
|
||||
* \param o another trace context
|
||||
* \returns true if the input trace context contains exactly the same set of
|
||||
* TraceContextElement instances, false otherwise.
|
||||
*
|
||||
* This method does not test for equality: the content of each matching
|
||||
* TraceContextElement could be different. It merely checks that both
|
||||
* trace contexts contain the same types of TraceContextElements.
|
||||
*/
|
||||
bool IsSimilar (const TraceContext &o) const;
|
||||
private:
|
||||
friend class TraceContextTest;
|
||||
// used exclusively for testing code.
|
||||
@@ -99,13 +142,15 @@ private:
|
||||
} * m_data;
|
||||
};
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const TraceContext &context);
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
TraceContext::Add (T const &context)
|
||||
TraceContext::AddElement (T const &context)
|
||||
{
|
||||
const TraceContextElement *parent;
|
||||
// if the following assignment fails, it is because the input
|
||||
@@ -119,8 +164,8 @@ TraceContext::Add (T const &context)
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
TraceContext::Get (T &context) const
|
||||
bool
|
||||
TraceContext::GetElement (T &context) const
|
||||
{
|
||||
TraceContextElement *parent;
|
||||
// if the following assignment fails, it is because the input
|
||||
@@ -128,10 +173,7 @@ TraceContext::Get (T &context) const
|
||||
parent = &context;
|
||||
uint8_t *data = (uint8_t *) &context;
|
||||
bool found = DoGet (T::GetUid (), data);
|
||||
if (!found)
|
||||
{
|
||||
NS_FATAL_ERROR ("Type not stored in TraceContext");
|
||||
}
|
||||
return found;
|
||||
}
|
||||
template <typename T>
|
||||
bool
|
||||
74
src/core/trace-doc.cc
Normal file
74
src/core/trace-doc.cc
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "trace-doc.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
TraceDoc::TraceDoc ()
|
||||
: m_help ("empty help")
|
||||
{}
|
||||
|
||||
TraceDoc::TraceDoc (std::string help)
|
||||
: m_help (help)
|
||||
{}
|
||||
TraceDoc::TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help)
|
||||
: m_help (help)
|
||||
{
|
||||
m_argVector.push_back (std::make_pair (arg0Type, arg0Help));
|
||||
}
|
||||
TraceDoc::TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help,
|
||||
std::string arg1Type,
|
||||
std::string arg1Help)
|
||||
: m_help (help)
|
||||
{
|
||||
m_argVector.push_back (std::make_pair (arg0Type, arg0Help));
|
||||
m_argVector.push_back (std::make_pair (arg1Type, arg1Help));
|
||||
}
|
||||
TraceDoc::TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help,
|
||||
std::string arg1Type,
|
||||
std::string arg1Help,
|
||||
std::string arg2Type,
|
||||
std::string arg2Help)
|
||||
: m_help (help)
|
||||
{
|
||||
m_argVector.push_back (std::make_pair (arg0Type, arg0Help));
|
||||
m_argVector.push_back (std::make_pair (arg1Type, arg1Help));
|
||||
m_argVector.push_back (std::make_pair (arg2Type, arg2Help));
|
||||
}
|
||||
TraceDoc::TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help,
|
||||
std::string arg1Type,
|
||||
std::string arg1Help,
|
||||
std::string arg2Type,
|
||||
std::string arg2Help,
|
||||
std::string arg3Type,
|
||||
std::string arg3Help)
|
||||
: m_help (help)
|
||||
{
|
||||
m_argVector.push_back (std::make_pair (arg0Type, arg0Help));
|
||||
m_argVector.push_back (std::make_pair (arg1Type, arg1Help));
|
||||
m_argVector.push_back (std::make_pair (arg2Type, arg2Help));
|
||||
m_argVector.push_back (std::make_pair (arg3Type, arg3Help));
|
||||
}
|
||||
std::string
|
||||
TraceDoc::GetHelp (void) const
|
||||
{
|
||||
return m_help;
|
||||
}
|
||||
TraceDoc::Iterator
|
||||
TraceDoc::ArgsBegin (void) const
|
||||
{
|
||||
return m_argVector.begin ();
|
||||
}
|
||||
TraceDoc::Iterator
|
||||
TraceDoc::ArgsEnd (void) const
|
||||
{
|
||||
return m_argVector.end ();
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
50
src/core/trace-doc.h
Normal file
50
src/core/trace-doc.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef TRACE_DOC_H
|
||||
#define TRACE_DOC_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TraceDoc
|
||||
{
|
||||
typedef std::vector<std::pair<std::string,std::string> > ArgVector;
|
||||
public:
|
||||
typedef ArgVector::const_iterator Iterator;
|
||||
TraceDoc ();
|
||||
TraceDoc (std::string help);
|
||||
TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help);
|
||||
TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help,
|
||||
std::string arg1Type,
|
||||
std::string arg1Help);
|
||||
TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help,
|
||||
std::string arg1Type,
|
||||
std::string arg1Help,
|
||||
std::string arg2Type,
|
||||
std::string arg2Help);
|
||||
TraceDoc (std::string help,
|
||||
std::string arg0Type,
|
||||
std::string arg0Help,
|
||||
std::string arg1Type,
|
||||
std::string arg1Help,
|
||||
std::string arg2Type,
|
||||
std::string arg2Help,
|
||||
std::string arg3Type,
|
||||
std::string arg3Help);
|
||||
std::string GetHelp (void) const;
|
||||
Iterator ArgsBegin (void) const;
|
||||
Iterator ArgsEnd (void) const;
|
||||
private:
|
||||
ArgVector m_argVector;
|
||||
std::string m_help;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* TRACE_DOC_H */
|
||||
107
src/core/trace-resolver.cc
Normal file
107
src/core/trace-resolver.cc
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "trace-resolver.h"
|
||||
#include "debug.h"
|
||||
|
||||
NS_DEBUG_COMPONENT_DEFINE ("TraceResolver");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
TraceResolver::TraceResolver ()
|
||||
: m_count (1)
|
||||
{}
|
||||
|
||||
TraceResolver::~TraceResolver ()
|
||||
{}
|
||||
|
||||
void
|
||||
TraceResolver::Ref (void)
|
||||
{
|
||||
m_count++;
|
||||
}
|
||||
void
|
||||
TraceResolver::Unref (void)
|
||||
{
|
||||
m_count--;
|
||||
if (m_count == 0)
|
||||
{
|
||||
NS_DEBUG ("delete "<<this);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
TraceResolver::GetElement (std::string path)
|
||||
{
|
||||
std::string::size_type cur = 1;
|
||||
// check that first char is "/"
|
||||
std::string::size_type next = path.find ("/", cur);
|
||||
std::string id = std::string (path, cur, next-1);
|
||||
return id;
|
||||
}
|
||||
std::string
|
||||
TraceResolver::GetSubpath (std::string path)
|
||||
{
|
||||
std::string::size_type cur = 1;
|
||||
// check that first char is "/"
|
||||
std::string::size_type next = path.find ("/", cur);
|
||||
std::string subpath;
|
||||
if (next != std::string::npos)
|
||||
{
|
||||
subpath = std::string (path, next, std::string::npos);
|
||||
}
|
||||
else
|
||||
{
|
||||
subpath = "";
|
||||
}
|
||||
return subpath;
|
||||
}
|
||||
|
||||
void
|
||||
TraceResolver::SourceCollection::AddUnique (std::string path,
|
||||
const TraceContext &context,
|
||||
const TraceDoc &doc)
|
||||
{
|
||||
for (SourceVector::const_iterator i = m_sources.begin (); i != m_sources.end (); i++)
|
||||
{
|
||||
if (i->path == path &&
|
||||
context.IsSimilar (i->context))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
struct Source source;
|
||||
source.path = path;
|
||||
source.context = context;
|
||||
source.doc = doc;
|
||||
m_sources.push_back (source);
|
||||
}
|
||||
TraceResolver::SourceCollection::Iterator
|
||||
TraceResolver::SourceCollection::Begin (void) const
|
||||
{
|
||||
return m_sources.begin ();
|
||||
}
|
||||
TraceResolver::SourceCollection::Iterator
|
||||
TraceResolver::SourceCollection::End (void) const
|
||||
{
|
||||
return m_sources.end ();
|
||||
}
|
||||
}//namespace ns3
|
||||
128
src/core/trace-resolver.h
Normal file
128
src/core/trace-resolver.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef TRACE_RESOLVER_H
|
||||
#define TRACE_RESOLVER_H
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include "trace-context.h"
|
||||
#include "trace-doc.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class CallbackBase;
|
||||
|
||||
/**
|
||||
* \brief the base class which is used to recursively perform trace
|
||||
* namespace resolution.
|
||||
* \ingroup tracing
|
||||
*
|
||||
* Although users could conceivably implement their own trace resolver
|
||||
* subclasses, doing so is complicated so, it is recommended to use
|
||||
* the default implementation ns3::CompositeTraceResolver instead.
|
||||
*/
|
||||
class TraceResolver
|
||||
{
|
||||
public:
|
||||
|
||||
TraceResolver ();
|
||||
virtual ~TraceResolver ();
|
||||
void Ref (void);
|
||||
void Unref (void);
|
||||
|
||||
/**
|
||||
* \param path the namespace path to resolver
|
||||
* \param cb the callback to connect to the matching namespace
|
||||
* \param context the context in which to store the trace context
|
||||
*
|
||||
* First, extract the leading path element from the input path, and
|
||||
* match this leading patch element against any terminal trace source
|
||||
* contained in this trace resolver.
|
||||
* Second, recursively resolve the rest of the path using other
|
||||
* objects if there are any.
|
||||
* If there is any TraceContextElement associated to one of the matching
|
||||
* elements, it should be added to the input TraceContext.
|
||||
*/
|
||||
virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context) = 0;
|
||||
/**
|
||||
* \param path the namespace path to resolver
|
||||
* \param cb the callback to disconnect in the matching namespace
|
||||
*
|
||||
* This method should behave as Connect.
|
||||
*/
|
||||
virtual void Disconnect (std::string path, CallbackBase const &cb) = 0;
|
||||
|
||||
class SourceCollection
|
||||
{
|
||||
public:
|
||||
struct Source
|
||||
{
|
||||
std::string path;
|
||||
TraceContext context;
|
||||
TraceDoc doc;
|
||||
};
|
||||
typedef std::vector<struct Source>::const_iterator Iterator;
|
||||
void AddUnique (std::string path,
|
||||
const TraceContext &context,
|
||||
const TraceDoc &doc);
|
||||
|
||||
Iterator Begin (void) const;
|
||||
Iterator End (void) const;
|
||||
private:
|
||||
typedef std::vector<struct Source> SourceVector;
|
||||
SourceVector m_sources;
|
||||
};
|
||||
/**
|
||||
* \param path the path to the current recursive level.
|
||||
* \param context the trace context associated to the current recursive level
|
||||
* \param collection the collection in which to gather every trace source found.
|
||||
*
|
||||
* This method is invoked recursively until all trace sources have been
|
||||
* stored in the output SourceCollection argument.
|
||||
*/
|
||||
virtual void CollectSources (std::string path, const TraceContext &context,
|
||||
SourceCollection *collection) = 0;
|
||||
|
||||
virtual void TraceAll (std::ostream &os, const TraceContext &context) = 0;
|
||||
protected:
|
||||
/**
|
||||
* \param path a namespace path
|
||||
* \returns the initial element of the path.
|
||||
*
|
||||
* If the input path is "/foo/...", the return
|
||||
* value is "foo".
|
||||
*/
|
||||
std::string GetElement (std::string path);
|
||||
/**
|
||||
* \param path a namespace path
|
||||
* \returns the subpath.
|
||||
*
|
||||
* If the input path is "/foo/bar/...", the return
|
||||
* value is "/bar/...".
|
||||
*/
|
||||
std::string GetSubpath (std::string path);
|
||||
private:
|
||||
uint32_t m_count;
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
#endif /* TRACE_RESOLVER_H */
|
||||
@@ -1,7 +1,6 @@
|
||||
/* -*- 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
|
||||
@@ -18,8 +17,15 @@
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "empty-trace-resolver.h"
|
||||
#include "trace-source.h"
|
||||
#include "trace-context.h"
|
||||
|
||||
ns3::EmptyTraceResolver::EmptyTraceResolver (TraceContext const &context)
|
||||
: TraceResolver (context)
|
||||
{}
|
||||
namespace ns3 {
|
||||
|
||||
void
|
||||
TraceSource::AddCallback (CallbackBase const & callback)
|
||||
{
|
||||
AddCallback (callback, TraceContext ());
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
61
src/core/trace-source.h
Normal file
61
src/core/trace-source.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef TRACE_SOURCE_H
|
||||
#define TRACE_SOURCE_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class CallbackBase;
|
||||
class TraceContext;
|
||||
|
||||
/**
|
||||
* \brief the base class for all trace sources
|
||||
*
|
||||
* Every trace source which wishes to be connectable and disconnectable with
|
||||
* the TraceResolver system should derive from this base class and implement
|
||||
* all three methods below.
|
||||
*/
|
||||
class TraceSource
|
||||
{
|
||||
public:
|
||||
virtual ~TraceSource () {}
|
||||
/**
|
||||
* \param callback the callback to connect to this trace source
|
||||
* \param context the context associated to the input callback which should be passed
|
||||
* back to the user.
|
||||
*/
|
||||
virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) = 0;
|
||||
/**
|
||||
* \param callback the callback to connect to this trace source
|
||||
*/
|
||||
void AddCallback (CallbackBase const & callback);
|
||||
/**
|
||||
* \param callback the callback to disconnect from this trace source
|
||||
*/
|
||||
virtual void RemoveCallback (CallbackBase const & callback) = 0;
|
||||
virtual void ConnectPrinter (std::ostream &os, TraceContext const &context) = 0;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* TRACE_SOURCE_H */
|
||||
@@ -19,8 +19,8 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "uid-manager.h"
|
||||
#include "ns3/fatal-error.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "fatal-error.h"
|
||||
#include "assert.h"
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
#define UV_TRACE_SOURCE_H
|
||||
|
||||
#include "callback-trace-source.h"
|
||||
#include "trace-source.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class UVTraceSourceBase {
|
||||
class UVTraceSourceBase : public TraceSource {
|
||||
public:
|
||||
typedef CallbackTraceSource<uint64_t, uint64_t> ChangeNotifyCallback;
|
||||
|
||||
@@ -42,11 +43,14 @@ public:
|
||||
}
|
||||
~UVTraceSourceBase () {}
|
||||
|
||||
void AddCallback (CallbackBase const & callback, TraceContext const & context) {
|
||||
virtual void AddCallback (CallbackBase const & callback, TraceContext const & context) {
|
||||
m_callback.AddCallback (callback, context);
|
||||
}
|
||||
void RemoveCallback (CallbackBase const & callback) {
|
||||
m_callback.RemoveCallback (callback);
|
||||
virtual void RemoveCallback (CallbackBase const & callback) {
|
||||
m_callback.RemoveCallback (callback);
|
||||
}
|
||||
virtual void ConnectPrinter (std::ostream &os, const TraceContext &context) {
|
||||
m_callback.ConnectPrinter (os, context);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -66,7 +70,7 @@ class SVTraceSource;
|
||||
|
||||
/**
|
||||
* \brief trace variables of type "unsigned integer"
|
||||
* \ingroup lowleveltracing
|
||||
* \ingroup tracing
|
||||
*
|
||||
* This template class implements a POD type: it
|
||||
* behaves like any other variable of type "unsigned integer"
|
||||
@@ -78,7 +82,7 @@ class SVTraceSource;
|
||||
* ns3::UVTraceSource<uint32_t> :
|
||||
\code
|
||||
#include <stdint.h>
|
||||
#include "ns3/uv-trace-source.h"
|
||||
#include "uv-trace-source.h"
|
||||
|
||||
ns3::UVTraceSource<uint32_t> var;
|
||||
\endcode
|
||||
@@ -22,8 +22,8 @@
|
||||
#include "uv-trace-source.h"
|
||||
#include "sv-trace-source.h"
|
||||
#include "trace-context.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "test.h"
|
||||
#include "callback.h"
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
@@ -42,6 +42,14 @@ def build(bld):
|
||||
'type-name.cc',
|
||||
'component-manager.cc',
|
||||
'random-variable-default-value.cc',
|
||||
'variable-tracer-test.cc',
|
||||
'trace-context.cc',
|
||||
'trace-context-element.cc',
|
||||
'trace-resolver.cc',
|
||||
'callback-trace-source.cc',
|
||||
'composite-trace-resolver.cc',
|
||||
'trace-doc.cc',
|
||||
'trace-source.cc',
|
||||
]
|
||||
|
||||
if sys.platform == 'win32':
|
||||
@@ -73,5 +81,16 @@ def build(bld):
|
||||
'component-manager.h',
|
||||
'type-traits.h',
|
||||
'random-variable-default-value.h',
|
||||
'trace-source.h',
|
||||
'uv-trace-source.h',
|
||||
'sv-trace-source.h',
|
||||
'fv-trace-source.h',
|
||||
'callback-trace-source.h',
|
||||
'trace-context.h',
|
||||
'trace-context-element.h',
|
||||
'trace-resolver.h',
|
||||
'composite-trace-resolver.h',
|
||||
'array-trace-resolver.h',
|
||||
'trace-doc.h',
|
||||
]
|
||||
|
||||
|
||||
@@ -59,6 +59,16 @@ CsmaTraceType::GetUid (void)
|
||||
static uint16_t uid = AllocateUid<CsmaTraceType> ("CsmaTraceType");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
CsmaTraceType::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::CsmaTraceType";
|
||||
}
|
||||
enum CsmaTraceType::Type
|
||||
CsmaTraceType::Get (void) const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
|
||||
CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
|
||||
@@ -452,20 +462,23 @@ CsmaNetDevice::TransmitReadyEvent (void)
|
||||
}
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
CsmaNetDevice::DoCreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
CsmaNetDevice::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
resolver->Add ("queue",
|
||||
MakeCallback (&Queue::CreateTraceResolver,
|
||||
PeekPointer (m_queue)));
|
||||
resolver->Add ("rx",
|
||||
m_rxTrace,
|
||||
CsmaTraceType (CsmaTraceType::RX));
|
||||
resolver->Add ("drop",
|
||||
m_dropTrace,
|
||||
CsmaTraceType (CsmaTraceType::DROP));
|
||||
return resolver;
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddComposite ("queue", m_queue);
|
||||
resolver->AddSource ("rx",
|
||||
TraceDoc ("receive MAC packet",
|
||||
"const Packet &", "packet received"),
|
||||
m_rxTrace,
|
||||
CsmaTraceType (CsmaTraceType::RX));
|
||||
resolver->AddSource ("drop",
|
||||
TraceDoc ("drop MAC packet",
|
||||
"const Packet &", "packet dropped"),
|
||||
m_dropTrace,
|
||||
CsmaTraceType (CsmaTraceType::DROP));
|
||||
resolver->SetParentResolver (NetDevice::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace ns3 {
|
||||
class Queue;
|
||||
class CsmaChannel;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the type of trace source from a CsmaNetDevice
|
||||
*/
|
||||
class CsmaTraceType : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
@@ -52,6 +55,11 @@ public:
|
||||
CsmaTraceType ();
|
||||
void Print (std::ostream &os) const;
|
||||
static uint16_t GetUid (void);
|
||||
std::string GetTypeName (void) const;
|
||||
/**
|
||||
* \returns the type of the trace source which generated an event.
|
||||
*/
|
||||
enum Type Get (void) const;
|
||||
private:
|
||||
enum Type m_type;
|
||||
};
|
||||
@@ -206,6 +214,13 @@ enum CsmaEncapsulationMode {
|
||||
protected:
|
||||
virtual bool DoNeedsArp (void) const;
|
||||
virtual void DoDispose (void);
|
||||
/**
|
||||
* Create a Trace Resolver for events in the net device.
|
||||
* (NOT TESTED)
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
|
||||
/**
|
||||
* Get a copy of the attached Queue.
|
||||
*
|
||||
@@ -321,12 +336,6 @@ private:
|
||||
* @see TransmitStart ()
|
||||
*/
|
||||
void TransmitReadyEvent (void);
|
||||
/**
|
||||
* Create a Trace Resolver for events in the net device.
|
||||
* (NOT TESTED)
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
|
||||
|
||||
/**
|
||||
* Aborts the transmission of the current packet
|
||||
|
||||
@@ -53,6 +53,11 @@ PointToPointTraceType::GetUid (void)
|
||||
static uint16_t uid = AllocateUid<PointToPointTraceType> ("PointToPointTraceType");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
PointToPointTraceType::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::PointToPointTraceType";
|
||||
}
|
||||
|
||||
|
||||
PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
|
||||
@@ -189,15 +194,17 @@ void PointToPointNetDevice::TransmitComplete (void)
|
||||
TransmitStart(p);
|
||||
}
|
||||
|
||||
TraceResolver* PointToPointNetDevice::DoCreateTraceResolver (
|
||||
TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
PointToPointNetDevice::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
resolver->Add ("queue",
|
||||
MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue)));
|
||||
resolver->Add ("rx",
|
||||
m_rxTrace,
|
||||
PointToPointTraceType ());
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddComposite ("queue", m_queue);
|
||||
resolver->AddSource ("rx",
|
||||
TraceDoc ("receive MAC packet",
|
||||
"const Packet &", "packet received"),
|
||||
m_rxTrace,
|
||||
PointToPointTraceType ());
|
||||
resolver->SetParentResolver (NetDevice::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,12 +38,16 @@ namespace ns3 {
|
||||
class Queue;
|
||||
class PointToPointChannel;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the type of trace source from a PointToPointNetDevice
|
||||
*/
|
||||
class PointToPointTraceType : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
PointToPointTraceType ();
|
||||
void Print (std::ostream &os) const;
|
||||
static uint16_t GetUid (void);
|
||||
std::string GetTypeName (void) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -152,6 +156,12 @@ public:
|
||||
*/
|
||||
void Receive (Packet& p);
|
||||
protected:
|
||||
/**
|
||||
* Create a Trace Resolver for events in the net device.
|
||||
*
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
virtual void DoDispose (void);
|
||||
/**
|
||||
* Get a copy of the attached Queue.
|
||||
@@ -237,12 +247,6 @@ private:
|
||||
*
|
||||
*/
|
||||
void TransmitComplete(void);
|
||||
/**
|
||||
* Create a Trace Resolver for events in the net device.
|
||||
*
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
virtual TraceResolver* DoCreateTraceResolver (TraceContext const &context);
|
||||
virtual bool DoNeedsArp (void) const;
|
||||
/**
|
||||
* Enumeration of the states of the transmit machine of the net device.
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/assert.h"
|
||||
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
#include "arp-cache.h"
|
||||
#include "arp-header.h"
|
||||
#include "ipv4-interface.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
ArpCache::ArpCache (Ptr<NetDevice> device, Ipv4Interface *interface)
|
||||
ArpCache::ArpCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
|
||||
: m_device (device),
|
||||
m_interface (interface),
|
||||
m_aliveTimeout (Seconds (120)),
|
||||
@@ -47,7 +47,7 @@ ArpCache::GetDevice (void) const
|
||||
return m_device;
|
||||
}
|
||||
|
||||
Ipv4Interface *
|
||||
Ptr<Ipv4Interface>
|
||||
ArpCache::GetInterface (void) const
|
||||
{
|
||||
return m_interface;
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
* \param device The hardware NetDevice associated with this ARP chache
|
||||
* \param interface the Ipv4Interface associated with this ARP chache
|
||||
*/
|
||||
ArpCache (Ptr<NetDevice> device, Ipv4Interface *interface);
|
||||
ArpCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
|
||||
~ArpCache ();
|
||||
/**
|
||||
* \return The NetDevice that this ARP cache is associated with
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
/**
|
||||
* \return the Ipv4Interface that this ARP cache is associated with
|
||||
*/
|
||||
Ipv4Interface *GetInterface (void) const;
|
||||
Ptr<Ipv4Interface> GetInterface (void) const;
|
||||
|
||||
void SetAliveTimeout (Time aliveTimeout);
|
||||
void SetDeadTimeout (Time deadTimeout);
|
||||
@@ -152,7 +152,7 @@ private:
|
||||
typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash>::iterator CacheI;
|
||||
|
||||
Ptr<NetDevice> m_device;
|
||||
Ipv4Interface *m_interface;
|
||||
Ptr<Ipv4Interface> m_interface;
|
||||
Time m_aliveTimeout;
|
||||
Time m_deadTimeout;
|
||||
Time m_waitReplyTimeout;
|
||||
|
||||
@@ -40,16 +40,15 @@ ArpIpv4Interface::ArpIpv4Interface (Ptr<Node> node, Ptr<NetDevice> device)
|
||||
ArpIpv4Interface::~ArpIpv4Interface ()
|
||||
{}
|
||||
|
||||
TraceResolver *
|
||||
ArpIpv4Interface::DoCreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
ArpIpv4Interface::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
if (GetDevice () != 0)
|
||||
{
|
||||
resolver->Add ("netdevice",
|
||||
MakeCallback (&NetDevice::CreateTraceResolver, PeekPointer (GetDevice ())));
|
||||
resolver->AddComposite ("netdevice", GetDevice ());
|
||||
}
|
||||
|
||||
resolver->SetParentResolver (Ipv4Interface::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,10 @@ class ArpIpv4Interface : public Ipv4Interface
|
||||
ArpIpv4Interface (Ptr<Node> node, Ptr<NetDevice> device);
|
||||
virtual ~ArpIpv4Interface ();
|
||||
|
||||
private:
|
||||
protected:
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
private:
|
||||
virtual void SendTo (Packet p, Ipv4Address dest);
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
|
||||
Ptr<Node> m_node;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/debug.h"
|
||||
#include "ns3/empty-trace-resolver.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/net-device.h"
|
||||
|
||||
@@ -58,12 +57,6 @@ ArpL3Protocol::DoDispose (void)
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
ArpL3Protocol::CreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return new EmptyTraceResolver (context);
|
||||
}
|
||||
|
||||
ArpCache *
|
||||
ArpL3Protocol::FindCache (Ptr<NetDevice> device)
|
||||
{
|
||||
@@ -75,7 +68,7 @@ ArpL3Protocol::FindCache (Ptr<NetDevice> device)
|
||||
}
|
||||
}
|
||||
Ptr<Ipv4L3Protocol> ipv4 = m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
|
||||
Ipv4Interface *interface = ipv4->FindInterfaceForDevice (device);
|
||||
Ptr<Ipv4Interface> interface = ipv4->FindInterfaceForDevice (device);
|
||||
ArpCache * cache = new ArpCache (device, interface);
|
||||
NS_ASSERT (device->IsBroadcast ());
|
||||
device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
|
||||
|
||||
@@ -48,8 +48,6 @@ public:
|
||||
*/
|
||||
ArpL3Protocol (Ptr<Node> node);
|
||||
virtual ~ArpL3Protocol ();
|
||||
|
||||
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
/**
|
||||
* \brief Recieve a packet
|
||||
*/
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#include "ascii-trace.h"
|
||||
|
||||
#include "ns3/trace-context.h"
|
||||
#include "ns3/trace-root.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/queue.h"
|
||||
|
||||
@@ -41,19 +41,19 @@ void
|
||||
AsciiTrace::TraceAllQueues (void)
|
||||
{
|
||||
Packet::EnableMetadata ();
|
||||
TraceRoot::Connect ("/nodes/*/devices/*/queue/enqueue",
|
||||
NodeList::Connect ("/nodes/*/devices/*/queue/enqueue",
|
||||
MakeCallback (&AsciiTrace::LogDevQueueEnqueue, this));
|
||||
TraceRoot::Connect ("/nodes/*/devices/*/queue/dequeue",
|
||||
NodeList::Connect ("/nodes/*/devices/*/queue/dequeue",
|
||||
MakeCallback (&AsciiTrace::LogDevQueueDequeue, this));
|
||||
TraceRoot::Connect ("/nodes/*/devices/*/queue/drop",
|
||||
NodeList::Connect ("/nodes/*/devices/*/queue/drop",
|
||||
MakeCallback (&AsciiTrace::LogDevQueueDrop, this));
|
||||
}
|
||||
void
|
||||
AsciiTrace::TraceAllNetDeviceRx (void)
|
||||
{
|
||||
Packet::EnableMetadata ();
|
||||
TraceRoot::Connect ("/nodes/*/devices/*/rx",
|
||||
MakeCallback (&AsciiTrace::LogDevRx, this));
|
||||
NodeList::Connect ("/nodes/*/devices/*/rx",
|
||||
MakeCallback (&AsciiTrace::LogDevRx, this));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -74,13 +74,14 @@ InternetNode::Construct (void)
|
||||
Object::AddInterface (ipv4L4Demux);
|
||||
}
|
||||
|
||||
void
|
||||
InternetNode::DoFillTraceResolver (CompositeTraceResolver &resolver)
|
||||
Ptr<TraceResolver>
|
||||
InternetNode::GetTraceResolver () const
|
||||
{
|
||||
Node::DoFillTraceResolver (resolver);
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
Ptr<Ipv4L3Protocol> ipv4 = QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
|
||||
resolver.Add ("ipv4",
|
||||
MakeCallback (&Ipv4L3Protocol::CreateTraceResolver, PeekPointer (ipv4)));
|
||||
resolver->AddComposite ("ipv4", ipv4);
|
||||
resolver->SetParentResolver (Node::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -42,8 +42,8 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void DoDispose(void);
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
private:
|
||||
virtual void DoFillTraceResolver (CompositeTraceResolver &resolver);
|
||||
bool ReceiveFromDevice (Ptr<NetDevice> device, const Packet &p, uint16_t protocolNumber) const;
|
||||
void Construct (void);
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ipv4-interface.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -39,18 +40,19 @@ Ipv4Interface::Ipv4Interface (Ptr<NetDevice> nd)
|
||||
Ipv4Interface::~Ipv4Interface ()
|
||||
{}
|
||||
|
||||
void
|
||||
Ipv4Interface::DoDispose (void)
|
||||
{
|
||||
m_netdevice = 0;
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
Ptr<NetDevice>
|
||||
Ipv4Interface::GetDevice (void) const
|
||||
{
|
||||
return m_netdevice;
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
Ipv4Interface::CreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return DoCreateTraceResolver (context);
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4Interface::SetAddress (Ipv4Address a)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <list>
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/object.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -60,9 +61,8 @@ class TraceContext;
|
||||
*
|
||||
* Subclasses must implement the two methods:
|
||||
* - Ipv4Interface::SendTo
|
||||
* - Ipv4Interface::DoCreateTraceResolver
|
||||
*/
|
||||
class Ipv4Interface
|
||||
class Ipv4Interface : public Object
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -73,17 +73,6 @@ public:
|
||||
Ipv4Interface (Ptr<NetDevice> nd);
|
||||
virtual ~Ipv4Interface();
|
||||
|
||||
/**
|
||||
* \param context the trace context to use to construct the
|
||||
* TraceResolver to return
|
||||
* \returns a TraceResolver which can resolve all traces
|
||||
* performed in this object. The caller must
|
||||
* delete the returned object.
|
||||
*
|
||||
* This method will delegate the work to the private DoCreateTraceResolver
|
||||
* method which is supposed to be implemented by subclasses.
|
||||
*/
|
||||
TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
/**
|
||||
* \returns the underlying NetDevice. This method can return
|
||||
* zero if this interface has no associated NetDevice.
|
||||
@@ -150,10 +139,10 @@ public:
|
||||
*/
|
||||
void Send(Packet p, Ipv4Address dest);
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
private:
|
||||
virtual void SendTo (Packet p, Ipv4Address dest) = 0;
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
|
||||
Ptr<NetDevice> m_netdevice;
|
||||
bool m_ifup;
|
||||
Ipv4Address m_address;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#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 "ns3/ipv4-address.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
@@ -88,30 +87,40 @@ Ipv4L3ProtocolTraceContextElement::GetUid (void)
|
||||
static uint16_t uid = AllocateUid<Ipv4L3ProtocolTraceContextElement> ("Ipv4L3ProtocolTraceContextElement");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
Ipv4L3ProtocolTraceContextElement::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::Ipv4L3ProtocolTraceContextElement";
|
||||
}
|
||||
|
||||
|
||||
Ipv4l3ProtocolInterfaceIndex::Ipv4l3ProtocolInterfaceIndex ()
|
||||
Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex ()
|
||||
: m_index (0)
|
||||
{}
|
||||
Ipv4l3ProtocolInterfaceIndex::Ipv4l3ProtocolInterfaceIndex (uint32_t index)
|
||||
Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex (uint32_t index)
|
||||
: m_index (index)
|
||||
{}
|
||||
uint32_t
|
||||
Ipv4l3ProtocolInterfaceIndex::Get (void) const
|
||||
Ipv4L3ProtocolInterfaceIndex::Get (void) const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
void
|
||||
Ipv4l3ProtocolInterfaceIndex::Print (std::ostream &os) const
|
||||
Ipv4L3ProtocolInterfaceIndex::Print (std::ostream &os) const
|
||||
{
|
||||
os << "ipv4-interface=" << m_index;
|
||||
}
|
||||
uint16_t
|
||||
Ipv4l3ProtocolInterfaceIndex::GetUid (void)
|
||||
Ipv4L3ProtocolInterfaceIndex::GetUid (void)
|
||||
{
|
||||
static uint16_t uid = AllocateUid<Ipv4l3ProtocolInterfaceIndex> ("Ipv4l3ProtocolInterfaceIndex");
|
||||
static uint16_t uid = AllocateUid<Ipv4L3ProtocolInterfaceIndex> ("Ipv4L3ProtocolInterfaceIndex");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
Ipv4L3ProtocolInterfaceIndex::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::Ipv4L3ProtocolInterfaceIndex";
|
||||
}
|
||||
|
||||
|
||||
Ipv4L3Protocol::Ipv4L3Protocol(Ptr<Node> node)
|
||||
@@ -131,10 +140,6 @@ Ipv4L3Protocol::~Ipv4L3Protocol ()
|
||||
void
|
||||
Ipv4L3Protocol::DoDispose (void)
|
||||
{
|
||||
for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
|
||||
{
|
||||
delete (*i);
|
||||
}
|
||||
m_interfaces.clear ();
|
||||
m_node = 0;
|
||||
m_staticRouting->Dispose ();
|
||||
@@ -145,7 +150,7 @@ Ipv4L3Protocol::DoDispose (void)
|
||||
void
|
||||
Ipv4L3Protocol::SetupLoopback (void)
|
||||
{
|
||||
Ipv4LoopbackInterface * interface = new Ipv4LoopbackInterface (m_node);
|
||||
Ptr<Ipv4LoopbackInterface> interface = Create<Ipv4LoopbackInterface> (m_node);
|
||||
interface->SetAddress (Ipv4Address::GetLoopback ());
|
||||
interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
|
||||
uint32_t index = AddIpv4Interface (interface);
|
||||
@@ -153,26 +158,27 @@ Ipv4L3Protocol::SetupLoopback (void)
|
||||
interface->SetUp ();
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
Ipv4L3Protocol::CreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
Ipv4L3Protocol::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
resolver->Add ("tx", m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX));
|
||||
resolver->Add ("rx", m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX));
|
||||
resolver->Add ("drop", m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP));
|
||||
resolver->Add ("interfaces",
|
||||
MakeCallback (&Ipv4L3Protocol::InterfacesCreateTraceResolver, this));
|
||||
return resolver;
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
Ipv4L3Protocol::InterfacesCreateTraceResolver (TraceContext const &context) const
|
||||
{
|
||||
ArrayTraceResolver<Ipv4Interface *, Ipv4l3ProtocolInterfaceIndex> *resolver =
|
||||
new ArrayTraceResolver<Ipv4Interface *,Ipv4l3ProtocolInterfaceIndex>
|
||||
(context,
|
||||
MakeCallback (&Ipv4L3Protocol::GetNInterfaces, this),
|
||||
MakeCallback (&Ipv4L3Protocol::GetInterface, this));
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddSource ("tx",
|
||||
TraceDoc ("send ipv4 packet to outgoing interface",
|
||||
"const Packet &", "packet sent",
|
||||
"uint32_t", "index of output ipv4 interface"),
|
||||
m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX));
|
||||
resolver->AddSource ("rx",
|
||||
TraceDoc ("receive ipv4 packet from incoming interface",
|
||||
"const Packet &", "packet received",
|
||||
"uint32_t", "index of input ipv4 interface"),
|
||||
m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX));
|
||||
resolver->AddSource ("drop",
|
||||
TraceDoc ("drop ipv4 packet",
|
||||
"const Packet &", "packet dropped"),
|
||||
m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP));
|
||||
resolver->AddArray ("interfaces",
|
||||
m_interfaces.begin (), m_interfaces.end (),
|
||||
Ipv4L3ProtocolInterfaceIndex ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@@ -265,18 +271,18 @@ Ipv4L3Protocol::RemoveRoute (uint32_t index)
|
||||
uint32_t
|
||||
Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
|
||||
{
|
||||
Ipv4Interface *interface = new ArpIpv4Interface (m_node, device);
|
||||
Ptr<Ipv4Interface> interface = Create<ArpIpv4Interface> (m_node, device);
|
||||
return AddIpv4Interface (interface);
|
||||
}
|
||||
uint32_t
|
||||
Ipv4L3Protocol::AddIpv4Interface (Ipv4Interface *interface)
|
||||
Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
|
||||
{
|
||||
uint32_t index = m_nInterfaces;
|
||||
m_interfaces.push_back (interface);
|
||||
m_nInterfaces++;
|
||||
return index;
|
||||
}
|
||||
Ipv4Interface *
|
||||
Ptr<Ipv4Interface>
|
||||
Ipv4L3Protocol::GetInterface (uint32_t index) const
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
@@ -296,7 +302,7 @@ Ipv4L3Protocol::GetNInterfaces (void) const
|
||||
return m_nInterfaces;
|
||||
}
|
||||
|
||||
Ipv4Interface *
|
||||
Ptr<Ipv4Interface>
|
||||
Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
|
||||
{
|
||||
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
|
||||
@@ -364,7 +370,7 @@ Ipv4L3Protocol::Send (Packet const &packet,
|
||||
for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
|
||||
ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
|
||||
{
|
||||
Ipv4Interface *outInterface = *ifaceIter;
|
||||
Ptr<Ipv4Interface> outInterface = *ifaceIter;
|
||||
Packet packetCopy = packet;
|
||||
|
||||
NS_ASSERT (packetCopy.GetSize () <= outInterface->GetMtu ());
|
||||
@@ -401,7 +407,7 @@ Ipv4L3Protocol::SendRealOut (bool found,
|
||||
return;
|
||||
}
|
||||
packet.AddHeader (ipHeader);
|
||||
Ipv4Interface *outInterface = GetInterface (route.GetInterface ());
|
||||
Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
|
||||
NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ());
|
||||
m_txTrace (packet, route.GetInterface ());
|
||||
if (route.IsGateway ())
|
||||
@@ -431,7 +437,7 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetD
|
||||
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
|
||||
i != m_interfaces.end (); i++)
|
||||
{
|
||||
Ipv4Interface *interface = *i;
|
||||
Ptr<Ipv4Interface> interface = *i;
|
||||
if (interface->GetDevice () == device)
|
||||
{
|
||||
if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ()))
|
||||
@@ -481,43 +487,43 @@ Ipv4L3Protocol::ForwardUp (Packet p, Ipv4Header const&ip)
|
||||
void
|
||||
Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
interface->SetAddress (address);
|
||||
}
|
||||
void
|
||||
Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
interface->SetNetworkMask (mask);
|
||||
}
|
||||
Ipv4Mask
|
||||
Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
return interface->GetNetworkMask ();
|
||||
}
|
||||
Ipv4Address
|
||||
Ipv4L3Protocol::GetAddress (uint32_t i) const
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
return interface->GetAddress ();
|
||||
}
|
||||
uint16_t
|
||||
Ipv4L3Protocol::GetMtu (uint32_t i) const
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
return interface->GetMtu ();
|
||||
}
|
||||
bool
|
||||
Ipv4L3Protocol::IsUp (uint32_t i) const
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
return interface->IsUp ();
|
||||
}
|
||||
void
|
||||
Ipv4L3Protocol::SetUp (uint32_t i)
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (i);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (i);
|
||||
interface->SetUp ();
|
||||
|
||||
// If interface address and network mask have been set, add a route
|
||||
@@ -533,7 +539,7 @@ Ipv4L3Protocol::SetUp (uint32_t i)
|
||||
void
|
||||
Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
|
||||
{
|
||||
Ipv4Interface *interface = GetInterface (ifaceIndex);
|
||||
Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
|
||||
interface->SetDown ();
|
||||
|
||||
// Remove all routes that are going through this interface
|
||||
|
||||
@@ -44,6 +44,9 @@ class Node;
|
||||
class TraceResolver;
|
||||
class TraceContext;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the type of trace source used by this Ipv4L3Protocol
|
||||
*/
|
||||
class Ipv4L3ProtocolTraceContextElement : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
@@ -54,23 +57,40 @@ public:
|
||||
};
|
||||
Ipv4L3ProtocolTraceContextElement ();
|
||||
Ipv4L3ProtocolTraceContextElement (enum Type type);
|
||||
/**
|
||||
* \returns true if this is a tx event, false otherwise.
|
||||
*/
|
||||
bool IsTx (void) const;
|
||||
/**
|
||||
* \returns true if this is a rx event, false otherwise.
|
||||
*/
|
||||
bool IsRx (void) const;
|
||||
/**
|
||||
* \returns true if this is a drop event, false otherwise.
|
||||
*/
|
||||
bool IsDrop (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
static uint16_t GetUid (void);
|
||||
std::string GetTypeName (void) const;
|
||||
private:
|
||||
enum Type m_type;
|
||||
};
|
||||
|
||||
class Ipv4l3ProtocolInterfaceIndex : public TraceContextElement
|
||||
/**
|
||||
* \brief hold in a TraceContext the index of an Ipv4Interface within the ipv4 stack of a Node
|
||||
*/
|
||||
class Ipv4L3ProtocolInterfaceIndex : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
Ipv4l3ProtocolInterfaceIndex ();
|
||||
Ipv4l3ProtocolInterfaceIndex (uint32_t index);
|
||||
Ipv4L3ProtocolInterfaceIndex ();
|
||||
Ipv4L3ProtocolInterfaceIndex (uint32_t index);
|
||||
/**
|
||||
* \returns the index of the Ipv4Interface within a Node.
|
||||
*/
|
||||
uint32_t Get (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
static uint16_t GetUid (void);
|
||||
std::string GetTypeName (void) const;
|
||||
private:
|
||||
uint32_t m_index;
|
||||
};
|
||||
@@ -85,15 +105,6 @@ public:
|
||||
Ipv4L3Protocol(Ptr<Node> node);
|
||||
virtual ~Ipv4L3Protocol ();
|
||||
|
||||
/**
|
||||
* \param context the trace context to use to construct the
|
||||
* TraceResolver to return
|
||||
* \returns a TraceResolver which can resolve all traces
|
||||
* performed in this object. The caller must
|
||||
* delete the returned object.
|
||||
*/
|
||||
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
|
||||
/**
|
||||
* \param ttl default ttl to use
|
||||
*
|
||||
@@ -109,7 +120,7 @@ public:
|
||||
* Try to find an Ipv4Interface whose NetDevice is equal to
|
||||
* the input NetDevice.
|
||||
*/
|
||||
Ipv4Interface *FindInterfaceForDevice (Ptr<const NetDevice> device);
|
||||
Ptr<Ipv4Interface> FindInterfaceForDevice (Ptr<const NetDevice> device);
|
||||
|
||||
/**
|
||||
* Lower layer calls this method after calling L3Demux::Lookup
|
||||
@@ -159,7 +170,7 @@ public:
|
||||
void RemoveRoute (uint32_t i);
|
||||
|
||||
uint32_t AddInterface (Ptr<NetDevice> device);
|
||||
Ipv4Interface * GetInterface (uint32_t i) const;
|
||||
Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
|
||||
uint32_t GetNInterfaces (void) const;
|
||||
|
||||
|
||||
@@ -178,6 +189,7 @@ public:
|
||||
protected:
|
||||
|
||||
virtual void DoDispose (void);
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -187,11 +199,10 @@ private:
|
||||
Ipv4Header const &ipHeader);
|
||||
bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetDevice> device);
|
||||
void ForwardUp (Packet p, Ipv4Header const&ip);
|
||||
uint32_t AddIpv4Interface (Ipv4Interface *interface);
|
||||
uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
|
||||
void SetupLoopback (void);
|
||||
TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const;
|
||||
|
||||
typedef std::list<Ipv4Interface*> Ipv4InterfaceList;
|
||||
typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
|
||||
typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
|
||||
|
||||
Ipv4InterfaceList m_interfaces;
|
||||
|
||||
@@ -54,6 +54,11 @@ Ipv4L4ProtocolTraceContextElement::GetUid (void)
|
||||
static uint16_t uid = AllocateUid<Ipv4L4ProtocolTraceContextElement> ("Ipv4L4ProtocolTraceContextElement");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
Ipv4L4ProtocolTraceContextElement::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::Ipv4L4ProtocolTraceContextElement";
|
||||
}
|
||||
|
||||
|
||||
Ipv4L4Demux::Ipv4L4Demux (Ptr<Node> node)
|
||||
@@ -78,21 +83,19 @@ Ipv4L4Demux::DoDispose (void)
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
Ipv4L4Demux::CreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
Ipv4L4Demux::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
|
||||
{
|
||||
Ptr<Ipv4L4Protocol> protocol = *i;
|
||||
std::string protValue;
|
||||
std::ostringstream oss (protValue);
|
||||
oss << (*i)->GetProtocolNumber ();
|
||||
std::ostringstream oss;
|
||||
oss << (unsigned int) (*i)->GetProtocolNumber ();
|
||||
Ipv4L4ProtocolTraceContextElement protocolNumber = (*i)->GetProtocolNumber ();
|
||||
resolver->Add (protValue,
|
||||
MakeCallback (&Ipv4L4Protocol::CreateTraceResolver, PeekPointer (protocol)),
|
||||
protocolNumber);
|
||||
resolver->AddComposite (oss.str (), protocol, protocolNumber);
|
||||
}
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
void
|
||||
|
||||
@@ -37,14 +37,21 @@ class Node;
|
||||
class TraceResolver;
|
||||
class TraceContext;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the protocol number of a L4 Protocol
|
||||
*/
|
||||
class Ipv4L4ProtocolTraceContextElement : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
Ipv4L4ProtocolTraceContextElement ();
|
||||
Ipv4L4ProtocolTraceContextElement (int protocolNumber);
|
||||
/**
|
||||
* \returns the protocol number as registered in the Ipv4L4Demux.
|
||||
*/
|
||||
int Get (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
static uint16_t GetUid (void);
|
||||
std::string GetTypeName (void) const;
|
||||
private:
|
||||
int m_protocolNumber;
|
||||
};
|
||||
@@ -59,14 +66,6 @@ public:
|
||||
Ipv4L4Demux (Ptr<Node> node);
|
||||
virtual ~Ipv4L4Demux();
|
||||
|
||||
/**
|
||||
* \param context the trace context to use to construct the
|
||||
* TraceResolver to return
|
||||
* \returns a TraceResolver which can resolve all traces
|
||||
* performed in this object. The caller must
|
||||
* delete the returned object.
|
||||
*/
|
||||
TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
/**
|
||||
* \param protocol a template for the protocol to add to this L4 Demux.
|
||||
* \returns the L4Protocol effectively added.
|
||||
@@ -95,8 +94,10 @@ public:
|
||||
* returned from the Ipv4L4Protocol::Insert method.
|
||||
*/
|
||||
void Remove (Ptr<Ipv4L4Protocol> protocol);
|
||||
private:
|
||||
protected:
|
||||
Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
virtual void DoDispose (void);
|
||||
private:
|
||||
typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
|
||||
L4List_t m_protocols;
|
||||
Ptr<Node> m_node;
|
||||
|
||||
@@ -37,10 +37,6 @@ class TraceContext;
|
||||
/**
|
||||
* \brief L4 Protocol base class
|
||||
*
|
||||
* All subclasses must implement:
|
||||
* - Ipv4L4Protocol::Copy
|
||||
* - Ipv4L4Protocol::CreateTraceResolver
|
||||
*
|
||||
* If you want to implement a new L4 protocol, all you have to do is
|
||||
* implement a subclass of this base class and add it to an L4Demux.
|
||||
*/
|
||||
@@ -59,8 +55,6 @@ public:
|
||||
*/
|
||||
int GetVersion() const;
|
||||
|
||||
virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
|
||||
|
||||
/**
|
||||
* \param p packet to forward up
|
||||
* \param source source address of packet received
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
* Authors:
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
|
||||
*/
|
||||
#include "ns3/empty-trace-resolver.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/eui48-address.h"
|
||||
@@ -34,13 +33,6 @@ Ipv4LoopbackInterface::Ipv4LoopbackInterface (Ptr<Node> node)
|
||||
{}
|
||||
Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()
|
||||
{}
|
||||
|
||||
TraceResolver *
|
||||
Ipv4LoopbackInterface::DoCreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return new EmptyTraceResolver (context);
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest)
|
||||
{
|
||||
|
||||
@@ -43,7 +43,6 @@ class Ipv4LoopbackInterface : public Ipv4Interface
|
||||
|
||||
private:
|
||||
virtual void SendTo (Packet p, Ipv4Address dest);
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
|
||||
|
||||
Ptr<Node> m_node;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "ns3/trace-root.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/trace-context.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/pcap-writer.h"
|
||||
@@ -50,8 +50,8 @@ PcapTrace::~PcapTrace ()
|
||||
void
|
||||
PcapTrace::TraceAllIp (void)
|
||||
{
|
||||
TraceRoot::Connect ("/nodes/*/ipv4/(tx|rx)",
|
||||
MakeCallback (&PcapTrace::LogIp, this));
|
||||
NodeList::Connect ("/nodes/*/ipv4/(tx|rx)",
|
||||
MakeCallback (&PcapTrace::LogIp, this));
|
||||
}
|
||||
|
||||
PcapWriter *
|
||||
@@ -83,7 +83,7 @@ void
|
||||
PcapTrace::LogIp (TraceContext const &context, Packet const &p, uint32_t interfaceIndex)
|
||||
{
|
||||
NodeListIndex nodeIndex;
|
||||
context.Get (nodeIndex);
|
||||
context.GetElement (nodeIndex);
|
||||
PcapWriter *writer = GetStream (nodeIndex.Get (), interfaceIndex);
|
||||
writer->WritePacket (p);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/empty-trace-resolver.h"
|
||||
#include "ns3/node.h"
|
||||
|
||||
#include "udp-l4-protocol.h"
|
||||
@@ -45,12 +44,6 @@ UdpL4Protocol::UdpL4Protocol (Ptr<Node> node)
|
||||
UdpL4Protocol::~UdpL4Protocol ()
|
||||
{}
|
||||
|
||||
TraceResolver *
|
||||
UdpL4Protocol::CreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return new EmptyTraceResolver (context);
|
||||
}
|
||||
|
||||
void
|
||||
UdpL4Protocol::DoDispose (void)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,6 @@ public:
|
||||
UdpL4Protocol (Ptr<Node> node);
|
||||
virtual ~UdpL4Protocol ();
|
||||
|
||||
virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
/**
|
||||
* \return A smart Socket pointer to a UdpSocket, allocated by this instance
|
||||
* of the UDP protocol
|
||||
|
||||
@@ -41,8 +41,8 @@ HierarchicalMobilityModel::HierarchicalMobilityModel (Ptr<MobilityModel> child,
|
||||
parentNotifier = Create<MobilityModelNotifier> ();
|
||||
parent->AddInterface (parentNotifier);
|
||||
}
|
||||
childNotifier->RegisterListener (MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
|
||||
parentNotifier->RegisterListener (MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
|
||||
childNotifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
|
||||
parentNotifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
|
||||
}
|
||||
|
||||
Ptr<MobilityModel>
|
||||
@@ -89,13 +89,13 @@ HierarchicalMobilityModel::DoGetSpeed (void) const
|
||||
}
|
||||
|
||||
void
|
||||
HierarchicalMobilityModel::ParentChanged (Ptr<const MobilityModel> model)
|
||||
HierarchicalMobilityModel::ParentChanged (const TraceContext &context, Ptr<const MobilityModel> model)
|
||||
{
|
||||
MobilityModel::NotifyCourseChange ();
|
||||
}
|
||||
|
||||
void
|
||||
HierarchicalMobilityModel::ChildChanged (Ptr<const MobilityModel> model)
|
||||
HierarchicalMobilityModel::ChildChanged (const TraceContext &context, Ptr<const MobilityModel> model)
|
||||
{
|
||||
MobilityModel::NotifyCourseChange ();
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ private:
|
||||
virtual void DoSet (const Position &position);
|
||||
virtual Speed DoGetSpeed (void) const;
|
||||
|
||||
void ParentChanged (Ptr<const MobilityModel> model);
|
||||
void ChildChanged (Ptr<const MobilityModel> model);
|
||||
void ParentChanged (const TraceContext &context, Ptr<const MobilityModel> model);
|
||||
void ChildChanged (const TraceContext &context, Ptr<const MobilityModel> model);
|
||||
|
||||
Ptr<MobilityModel> m_child;
|
||||
Ptr<MobilityModel> m_parent;
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "mobility-model-notifier.h"
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "ns3/trace-doc.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -32,37 +34,24 @@ MobilityModelNotifier::MobilityModelNotifier ()
|
||||
SetInterfaceId (MobilityModelNotifier::iid);
|
||||
}
|
||||
|
||||
void
|
||||
MobilityModelNotifier::RegisterListener (Listener listener)
|
||||
{
|
||||
m_listeners.push_back (listener);
|
||||
}
|
||||
void
|
||||
MobilityModelNotifier::UnregisterListener (Listener callback)
|
||||
{
|
||||
for (std::list<Listener>::iterator i = m_listeners.begin ();
|
||||
i != m_listeners.end ();)
|
||||
{
|
||||
Listener listener = *i;
|
||||
if (listener.IsEqual (callback))
|
||||
{
|
||||
i = m_listeners.erase (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
MobilityModelNotifier::Notify (Ptr<const MobilityModel> position) const
|
||||
{
|
||||
for (std::list<Listener>::const_iterator i = m_listeners.begin ();
|
||||
i != m_listeners.end (); i++)
|
||||
{
|
||||
Listener listener = *i;
|
||||
listener (position);
|
||||
}
|
||||
m_trace (position);
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
MobilityModelNotifier::GetTraceResolver (void) const
|
||||
{
|
||||
Ptr<CompositeTraceResolver> resolver =
|
||||
Create<CompositeTraceResolver> ();
|
||||
resolver->AddSource ("course-change",
|
||||
TraceDoc ("The value of the speed vector changed",
|
||||
"Ptr<const MobilityModel>",
|
||||
"the mobility model whose course changed"),
|
||||
m_trace);
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/component-manager.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/callback-trace-source.h"
|
||||
#include "mobility-model.h"
|
||||
|
||||
namespace ns3 {
|
||||
@@ -37,8 +38,6 @@ public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
|
||||
typedef Callback<void,Ptr<const MobilityModel> > Listener;
|
||||
|
||||
/**
|
||||
* Create a new position notifier
|
||||
*/
|
||||
@@ -48,23 +47,10 @@ public:
|
||||
* \param position the position which just changed.
|
||||
*/
|
||||
void Notify (Ptr<const MobilityModel> position) const;
|
||||
|
||||
/**
|
||||
* \param listener listener to add
|
||||
*
|
||||
* The listener will be notified upon every position change.
|
||||
*/
|
||||
void RegisterListener (Listener listener);
|
||||
/**
|
||||
* \param listener listener to remove
|
||||
*
|
||||
* The listener will not be notified anymore upon every
|
||||
* position change. It is not an error to try to unregister
|
||||
* a non-registered liste
|
||||
*/
|
||||
void UnregisterListener (Listener listener);
|
||||
protected:
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
private:
|
||||
std::list<Listener> m_listeners;
|
||||
CallbackTraceSource<Ptr<const MobilityModel> > m_trace;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/debug.h"
|
||||
#include "ns3/trace-resolver.h"
|
||||
|
||||
|
||||
#include "channel.h"
|
||||
@@ -183,12 +184,6 @@ NetDevice::Send(const Packet& p, const Address& dest, uint16_t protocolNumber)
|
||||
}
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
NetDevice::CreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return DoCreateTraceResolver (context);
|
||||
}
|
||||
|
||||
Ptr<Channel>
|
||||
NetDevice::GetChannel (void) const
|
||||
{
|
||||
|
||||
@@ -62,14 +62,6 @@ public:
|
||||
static const InterfaceId iid;
|
||||
virtual ~NetDevice();
|
||||
|
||||
/**
|
||||
* \param context the trace context to use to construct the
|
||||
* TraceResolver to return
|
||||
* \returns a TraceResolver which can resolve all traces
|
||||
* performed in this object. The caller must
|
||||
* delete the returned object.
|
||||
*/
|
||||
TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
|
||||
/**
|
||||
* \return the channel this NetDevice is connected to. The value
|
||||
@@ -282,15 +274,6 @@ public:
|
||||
* Subclasses must implement this method.
|
||||
*/
|
||||
virtual bool DoNeedsArp (void) const = 0;
|
||||
/**
|
||||
* \param context the trace context to associated to the
|
||||
* trace resolver.
|
||||
* \returns a trace resolver associated to the input context.
|
||||
* the caller takes ownership of the pointer returned.
|
||||
*
|
||||
* Subclasses must implement this method.
|
||||
*/
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
|
||||
/**
|
||||
* \returns the channel associated to this NetDevice.
|
||||
*
|
||||
|
||||
@@ -20,24 +20,12 @@
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
|
||||
*/
|
||||
|
||||
#include "ns3/array-trace-resolver.h"
|
||||
#include "ns3/trace-root.h"
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/simulation-singleton.h"
|
||||
#include "node-list.h"
|
||||
#include "node.h"
|
||||
|
||||
namespace {
|
||||
static class Initialization
|
||||
{
|
||||
public:
|
||||
Initialization ()
|
||||
{
|
||||
ns3::TraceRoot::Register ("nodes", ns3::MakeCallback (&ns3::NodeList::CreateTraceResolver));
|
||||
}
|
||||
} g_initialization;
|
||||
}
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NodeListIndex::NodeListIndex ()
|
||||
@@ -62,6 +50,11 @@ NodeListIndex::Get (void) const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
std::string
|
||||
NodeListIndex::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::NodeListIndex";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -74,9 +67,9 @@ public:
|
||||
~NodeListPriv ();
|
||||
|
||||
uint32_t Add (Ptr<Node> node);
|
||||
NodeList::Iterator Begin (void);
|
||||
NodeList::Iterator End (void);
|
||||
TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
NodeList::Iterator Begin (void) const;
|
||||
NodeList::Iterator End (void) const;
|
||||
Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
Ptr<Node> GetNode (uint32_t n);
|
||||
uint32_t GetNNodes (void);
|
||||
|
||||
@@ -108,12 +101,12 @@ NodeListPriv::Add (Ptr<Node> node)
|
||||
|
||||
}
|
||||
NodeList::Iterator
|
||||
NodeListPriv::Begin (void)
|
||||
NodeListPriv::Begin (void) const
|
||||
{
|
||||
return m_nodes.begin ();
|
||||
}
|
||||
NodeList::Iterator
|
||||
NodeListPriv::End (void)
|
||||
NodeListPriv::End (void) const
|
||||
{
|
||||
return m_nodes.end ();
|
||||
}
|
||||
@@ -130,14 +123,11 @@ NodeListPriv::GetNode (uint32_t n)
|
||||
}
|
||||
|
||||
|
||||
TraceResolver *
|
||||
NodeListPriv::CreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
NodeListPriv::GetTraceResolver (void) const
|
||||
{
|
||||
ArrayTraceResolver<Ptr<Node>, NodeListIndex> *resolver =
|
||||
new ArrayTraceResolver<Ptr<Node>, NodeListIndex>
|
||||
(context,
|
||||
MakeCallback (&NodeListPriv::GetNNodes, this),
|
||||
MakeCallback (&NodeListPriv::GetNode, this));
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddArray ("nodes", Begin (), End (), NodeListIndex ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@@ -165,17 +155,30 @@ NodeList::End (void)
|
||||
{
|
||||
return SimulationSingleton<NodeListPriv>::Get ()->End ();
|
||||
}
|
||||
TraceResolver *
|
||||
NodeList::CreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return SimulationSingleton<NodeListPriv>::Get ()->CreateTraceResolver (context);
|
||||
}
|
||||
Ptr<Node>
|
||||
NodeList::GetNode (uint32_t n)
|
||||
{
|
||||
return SimulationSingleton<NodeListPriv>::Get ()->GetNode (n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
NodeList::Connect (std::string name, const CallbackBase &cb)
|
||||
{
|
||||
SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ()->Connect (name, cb, TraceContext ());
|
||||
}
|
||||
void
|
||||
NodeList::Disconnect (std::string name, const CallbackBase &cb)
|
||||
{
|
||||
SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ()->Disconnect (name, cb);
|
||||
}
|
||||
void
|
||||
NodeList::TraceAll (std::ostream &os)
|
||||
{
|
||||
SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ()->TraceAll (os, TraceContext ());
|
||||
}
|
||||
Ptr<TraceResolver>
|
||||
NodeList::GetTraceResolver (void)
|
||||
{
|
||||
return SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ();
|
||||
}
|
||||
}//namespace ns3
|
||||
|
||||
@@ -29,9 +29,12 @@
|
||||
namespace ns3 {
|
||||
|
||||
class Node;
|
||||
class CallbackBase;
|
||||
class TraceResolver;
|
||||
class TraceContext;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the index of a node within a NodeList.
|
||||
*/
|
||||
class NodeListIndex : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
@@ -39,7 +42,11 @@ public:
|
||||
NodeListIndex (uint32_t index);
|
||||
void Print (std::ostream &os);
|
||||
static uint16_t GetUid (void);
|
||||
/**
|
||||
* \returns the index of the node within the NodeList
|
||||
*/
|
||||
uint32_t Get (void) const;
|
||||
std::string GetTypeName (void) const;
|
||||
private:
|
||||
uint32_t m_index;
|
||||
};
|
||||
@@ -53,7 +60,7 @@ private:
|
||||
class NodeList
|
||||
{
|
||||
public:
|
||||
typedef std::vector< Ptr<Node> >::iterator Iterator;
|
||||
typedef std::vector< Ptr<Node> >::const_iterator Iterator;
|
||||
|
||||
/**
|
||||
* \param node node to add
|
||||
@@ -73,19 +80,30 @@ public:
|
||||
* list.
|
||||
*/
|
||||
static Iterator End (void);
|
||||
/**
|
||||
* \param context trace context to use for trace resolver
|
||||
* to create.
|
||||
* \returns the requested trace resolver. The caller
|
||||
* takes ownership of the returned pointer.
|
||||
*/
|
||||
static TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
|
||||
/**
|
||||
* \param n index of requested node.
|
||||
* \returns the Node associated to index n.
|
||||
*/
|
||||
static Ptr<Node> GetNode (uint32_t n);
|
||||
/**
|
||||
* \param name namespace regexp to match
|
||||
* \param cb callback to connect
|
||||
*
|
||||
* Connect input callback to all trace sources which match
|
||||
* the input namespace regexp.
|
||||
*/
|
||||
static void Connect (std::string name, const CallbackBase &cb);
|
||||
/**
|
||||
* \param name namespace regexp to match
|
||||
* \param cb callback to connect
|
||||
*
|
||||
* Disconnect input callback from all trace sources which match
|
||||
* the input namespace regexp.
|
||||
*/
|
||||
static void Disconnect (std::string name, const CallbackBase &cb);
|
||||
static void TraceAll (std::ostream &os);
|
||||
static Ptr<TraceResolver> GetTraceResolver (void);
|
||||
private:
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "packet-socket-factory.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "ns3/array-trace-resolver.h"
|
||||
|
||||
namespace ns3{
|
||||
|
||||
@@ -53,6 +52,11 @@ NodeNetDeviceIndex::GetUid (void)
|
||||
static uint16_t uid = AllocateUid<NodeNetDeviceIndex> ("NodeNetDeviceIndex");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
NodeNetDeviceIndex::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::NodeNetDeviceIndex";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -82,11 +86,12 @@ Node::Construct (void)
|
||||
Node::~Node ()
|
||||
{}
|
||||
|
||||
TraceResolver *
|
||||
Node::CreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
Node::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
DoFillTraceResolver (*resolver);
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddArray ("devices", m_devices.begin (), m_devices.end (), NodeNetDeviceIndex ());
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@@ -141,25 +146,6 @@ Node::GetNApplications (void) const
|
||||
return m_applications.size ();
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
Node::CreateDevicesTraceResolver (const TraceContext &context)
|
||||
{
|
||||
ArrayTraceResolver<Ptr<NetDevice>,NodeNetDeviceIndex> *resolver =
|
||||
new ArrayTraceResolver<Ptr<NetDevice>,NodeNetDeviceIndex>
|
||||
(context,
|
||||
MakeCallback (&Node::GetNDevices, this),
|
||||
MakeCallback (&Node::GetDevice, this));
|
||||
|
||||
return resolver;
|
||||
}
|
||||
|
||||
void
|
||||
Node::DoFillTraceResolver (CompositeTraceResolver &resolver)
|
||||
{
|
||||
resolver.Add ("devices",
|
||||
MakeCallback (&Node::CreateDevicesTraceResolver, this));
|
||||
}
|
||||
|
||||
void
|
||||
Node::DoDispose()
|
||||
{
|
||||
|
||||
@@ -37,13 +37,20 @@ class Packet;
|
||||
class Address;
|
||||
class CompositeTraceResolver;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the index of a NetDevice within a Node
|
||||
*/
|
||||
class NodeNetDeviceIndex : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
NodeNetDeviceIndex ();
|
||||
NodeNetDeviceIndex (uint32_t index);
|
||||
/**
|
||||
* \returns the index of the NetDevice within its container Node.
|
||||
*/
|
||||
uint32_t Get (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
std::string GetTypeName (void) const;
|
||||
static uint16_t GetUid (void);
|
||||
private:
|
||||
uint32_t m_index;
|
||||
@@ -84,17 +91,6 @@ public:
|
||||
|
||||
virtual ~Node();
|
||||
|
||||
/**
|
||||
* \param context the trace context for the TraceResolver to create
|
||||
* \returns a newly-created TraceResolver. The caller takes
|
||||
* ownership of the returned pointer.
|
||||
*
|
||||
* Request the Node to create a trace resolver. This method
|
||||
* could be used directly by a user who needs access to very low-level
|
||||
* trace configuration.
|
||||
*/
|
||||
TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
|
||||
/**
|
||||
* \returns the unique id of this node.
|
||||
*
|
||||
@@ -183,23 +179,15 @@ public:
|
||||
void UnregisterProtocolHandler (ProtocolHandler handler);
|
||||
|
||||
protected:
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
/**
|
||||
* The dispose method. Subclasses must override this method
|
||||
* and must chain up to it by calling Node::DoDispose at the
|
||||
* end of their own DoDispose method.
|
||||
*/
|
||||
virtual void DoDispose (void);
|
||||
/**
|
||||
* \param resolver the resolver to store trace sources in.
|
||||
*
|
||||
* If a subclass wants to add new traces to a Node, it needs
|
||||
* to override this method and record the new trace sources
|
||||
* in the input resolver. Subclasses also _must_ chain up to
|
||||
* their parent's DoFillTraceResolver method prior
|
||||
* to recording they own trace sources.
|
||||
*/
|
||||
virtual void DoFillTraceResolver (CompositeTraceResolver &resolver);
|
||||
private:
|
||||
|
||||
/**
|
||||
* \param device the device added to this Node.
|
||||
*
|
||||
@@ -213,7 +201,6 @@ private:
|
||||
bool ReceiveFromDevice (Ptr<NetDevice> device, const Packet &packet,
|
||||
uint16_t protocol, const Address &from);
|
||||
void Construct (void);
|
||||
TraceResolver *CreateDevicesTraceResolver (const TraceContext &context);
|
||||
|
||||
struct ProtocolHandlerEntry {
|
||||
ProtocolHandler handler;
|
||||
|
||||
@@ -32,6 +32,11 @@ static ClassIdDefaultValue g_classIdDefaultValue ("Queue", "Packet Queue",
|
||||
Queue::iid, "DropTailQueue");
|
||||
|
||||
|
||||
std::string
|
||||
QueueTraceType::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::QueueTraceType";
|
||||
}
|
||||
uint16_t
|
||||
QueueTraceType::GetUid (void)
|
||||
{
|
||||
@@ -94,13 +99,23 @@ Queue::~Queue()
|
||||
NS_DEBUG("Queue::~Queue ()");
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
Queue::CreateTraceResolver (TraceContext const &context)
|
||||
Ptr<TraceResolver>
|
||||
Queue::GetTraceResolver (void) const
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
resolver->Add ("enqueue", m_traceEnqueue, QueueTraceType (QueueTraceType::ENQUEUE));
|
||||
resolver->Add ("dequeue", m_traceDequeue, QueueTraceType (QueueTraceType::DEQUEUE));
|
||||
resolver->Add ("drop", m_traceDrop, QueueTraceType (QueueTraceType::DROP));
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddSource ("enqueue",
|
||||
TraceDoc ("store packet in queue",
|
||||
"const Packet &", "packet queued"),
|
||||
m_traceEnqueue, QueueTraceType (QueueTraceType::ENQUEUE));
|
||||
resolver->AddSource ("dequeue",
|
||||
TraceDoc ("remove packet from queue",
|
||||
"const Packet &", "packet dequeued"),
|
||||
m_traceDequeue, QueueTraceType (QueueTraceType::DEQUEUE));
|
||||
resolver->AddSource ("drop",
|
||||
TraceDoc ("drop packet from queue",
|
||||
"const Packet &", "packet dropped"),
|
||||
m_traceDrop, QueueTraceType (QueueTraceType::DROP));
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace ns3 {
|
||||
|
||||
class StringEnumDefaultValue;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the type of a trace source
|
||||
*/
|
||||
class QueueTraceType : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
@@ -48,10 +51,20 @@ public:
|
||||
static uint16_t GetUid (void);
|
||||
QueueTraceType ();
|
||||
QueueTraceType (enum Type type);
|
||||
/**
|
||||
* \returns true if this is an enqueue event, false otherwise.
|
||||
*/
|
||||
bool IsEnqueue (void) const;
|
||||
/**
|
||||
* \returns true if this is a dequeue event, false otherwise.
|
||||
*/
|
||||
bool IsDequeue (void) const;
|
||||
/**
|
||||
* \returns true if this is a drop event, false otherwise.
|
||||
*/
|
||||
bool IsDrop (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
std::string GetTypeName (void) const;
|
||||
private:
|
||||
enum Type m_type;
|
||||
};
|
||||
@@ -69,8 +82,6 @@ public:
|
||||
|
||||
Queue ();
|
||||
virtual ~Queue ();
|
||||
|
||||
TraceResolver *CreateTraceResolver (TraceContext const &context);
|
||||
|
||||
/**
|
||||
* \return true if the queue is empty; false otherwise
|
||||
@@ -167,6 +178,7 @@ private:
|
||||
virtual bool DoPeek (Packet &p) = 0;
|
||||
|
||||
protected:
|
||||
Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
// called by subclasses to notify parent of packet drops.
|
||||
void Drop (const Packet& p);
|
||||
|
||||
|
||||
@@ -1407,27 +1407,6 @@ GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v)
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class GlobalRouterTestNode : public Node
|
||||
{
|
||||
public:
|
||||
GlobalRouterTestNode ();
|
||||
|
||||
private:
|
||||
virtual void DoAddDevice (Ptr<NetDevice> device) const {};
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
|
||||
};
|
||||
|
||||
GlobalRouterTestNode::GlobalRouterTestNode ()
|
||||
{
|
||||
// Ptr<Ipv4L3Protocol> ipv4 = Create<Ipv4L3Protocol> (this);
|
||||
}
|
||||
|
||||
TraceResolver*
|
||||
GlobalRouterTestNode::DoCreateTraceResolver (TraceContext const &context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
class GlobalRouteManagerImplTest : public Test {
|
||||
public:
|
||||
GlobalRouteManagerImplTest ();
|
||||
|
||||
100
utils/print-trace-sources.cc
Normal file
100
utils/print-trace-sources.cc
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/trace-resolver.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/csma-net-device.h"
|
||||
#include "ns3/queue.h"
|
||||
#include "ns3/mobility-model-notifier.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
void
|
||||
PrintSimpleText (const TraceResolver::SourceCollection *sources, std::ostream &os)
|
||||
{
|
||||
for (TraceResolver::SourceCollection::Iterator i = sources->Begin (); i != sources->End (); i++)
|
||||
{
|
||||
os << "source=" << i->path << std::endl;
|
||||
os << "TraceContext=[";
|
||||
i->context.PrintAvailable (os, ",");
|
||||
os << "]" << std::endl;
|
||||
os << "help=\"" << i->doc.GetHelp () << "\"" << std::endl;
|
||||
os << "void TraceSinkCallback (const TraceContext &";
|
||||
for (TraceDoc::Iterator k = i->doc.ArgsBegin (); k != i->doc.ArgsEnd (); k++)
|
||||
{
|
||||
os << ", " << k->first;
|
||||
}
|
||||
os << ")" << std::endl;
|
||||
os << "argument 1 -- the trace context associated to the connected trace source." << std::endl;
|
||||
uint32_t k = 2;
|
||||
for (TraceDoc::Iterator j = i->doc.ArgsBegin (); j != i->doc.ArgsEnd (); j++)
|
||||
{
|
||||
os << "argument " << k << " -- " << j->second << "." << std::endl;
|
||||
k++;
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
void
|
||||
PrintDoxygenText (const TraceResolver::SourceCollection *sources, std::ostream &os)
|
||||
{
|
||||
uint32_t z = 0;
|
||||
for (TraceResolver::SourceCollection::Iterator i = sources->Begin (); i != sources->End (); i++)
|
||||
{
|
||||
os << "///" << std::endl;
|
||||
os << "/// \\ingroup TraceSourceList" << std::endl;
|
||||
os << "/// \\brief " << i->doc.GetHelp () << std::endl;
|
||||
os << "/// \\param arg1 the trace context associated to the connected trace source." << std::endl;
|
||||
uint32_t j = 2;
|
||||
for (TraceDoc::Iterator l = i->doc.ArgsBegin (); l != i->doc.ArgsEnd (); l++)
|
||||
{
|
||||
os << "/// \\param arg" << j << " " << l->second << "." << std::endl;
|
||||
j++;
|
||||
}
|
||||
os << "///" << std::endl;
|
||||
os << "///" << std::endl;
|
||||
os << "/// The path to this trace source is: " << i->path << "." << std::endl;
|
||||
os << "///" << std::endl;
|
||||
if (i->context.Begin ().IsLast ())
|
||||
{
|
||||
os << "/// No data can be extracted from \\p arg1 with ns3::TraceContext::GetElement." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "/// The following classes can be extracted from \\p arg1 with " << std::endl;
|
||||
os << "/// ns3::TraceContext::GetElement:" << std::endl;
|
||||
for (TraceContext::Iterator m = i->context.Begin (); !m.IsLast (); m.Next ())
|
||||
{
|
||||
os << "/// - " << m.Get () << std::endl;
|
||||
}
|
||||
}
|
||||
os << "void TraceSinkCallback" << z << " (const TraceContext & arg1" ;
|
||||
j = 2;
|
||||
for (TraceDoc::Iterator k = i->doc.ArgsBegin (); k != i->doc.ArgsEnd (); k++)
|
||||
{
|
||||
os << ", " << k->first << " arg" << j;
|
||||
j++;
|
||||
}
|
||||
os << ");" << std::endl;
|
||||
os << std::endl;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Ptr<Node> node = Create<InternetNode> ();
|
||||
node->AddInterface (Create<MobilityModelNotifier> ());
|
||||
|
||||
Ptr<PointToPointNetDevice> p2p = Create<PointToPointNetDevice> (node);
|
||||
p2p->AddQueue (Queue::CreateDefault ());
|
||||
Ptr<CsmaNetDevice> csma = Create<CsmaNetDevice> (node);
|
||||
csma->AddQueue (Queue::CreateDefault ());
|
||||
|
||||
TraceResolver::SourceCollection collection;
|
||||
NodeList::GetTraceResolver ()->CollectSources ("", TraceContext (), &collection);
|
||||
PrintDoxygenText (&collection, std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -19,3 +19,7 @@ def build(bld):
|
||||
|
||||
obj = bld.create_ns3_program('replay-simulation', ['simulator'])
|
||||
obj.source = 'replay-simulation.cc'
|
||||
|
||||
obj = bld.create_ns3_program('print-trace-sources',
|
||||
['internet-node', 'csma-cd', 'point-to-point'])
|
||||
obj.source = 'print-trace-sources.cc'
|
||||
|
||||
Reference in New Issue
Block a user