diff --git a/.hgignore b/.hgignore index 6754560cf..8bbd0a32f 100644 --- a/.hgignore +++ b/.hgignore @@ -6,5 +6,6 @@ build .*\.sconsign doc/html.* doc/latex.* +doc/trace-source-list.h .lock-wscript .waf* diff --git a/doc/doxygen.conf b/doc/doxygen.conf index fc6fd25fa..ac0f72a0e 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -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 diff --git a/doc/main.txt b/doc/main.txt index 3fc144687..37e1ed92d 100644 --- a/doc/main.txt +++ b/doc/main.txt @@ -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 diff --git a/doc/namespace-2.dia b/doc/namespace-2.dia new file mode 100644 index 000000000..5cd5ed59e --- /dev/null +++ b/doc/namespace-2.dia @@ -0,0 +1,1658 @@ + + + + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/devices/[0-n]# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #NodeList# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Node# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/nodes/[0-n]# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/udp# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/rx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/netdevice# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/ipv4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/interfaces/[0-n]# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/rx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/rx# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/enqueue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/dequeue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/drop# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #InternetNode# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #PointToPointNetDevice# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Ipv4L3Protocol# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Ipv4Interface# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #CsmaNetDevice# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/enqueue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/dequeue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #/drop# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Queue# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/namespace-2.png b/doc/namespace-2.png new file mode 100644 index 000000000..7ea379c82 Binary files /dev/null and b/doc/namespace-2.png differ diff --git a/doc/trace-source-list.h b/doc/trace-source-list.h new file mode 100644 index 000000000..c23d06ece --- /dev/null +++ b/doc/trace-source-list.h @@ -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 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); + diff --git a/doc/tracing.h b/doc/tracing.h new file mode 100644 index 000000000..45e7d9db5 --- /dev/null +++ b/doc/tracing.h @@ -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 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 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 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 *PeekSomethingTraceSource (void) const + * { + * return &m_doSomething + * } + * private: + * // report every "something" function call. + * CallbackTraceSource 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 *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 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 GetTraceResolver (void) const; + * private: + * // the new trace source to export. + * CallbackTraceSource 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 + * MyModel::GetTraceResolver (void) const + * { + * // create an empty trace resolver + * Ptr resolver = Create (); + * // 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 GetTraceResolver (void) const; + * private: + * Ptr m_model; + * }; + * + * Ptr + * MyNetDevice::GetTraceResolver (void) const + * { + * Ptr 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 m_rxSource; + * CallbackTraceSource m_txSource; + * CallbackTraceSource 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 m_rxSource; + * CallbackTraceSource m_txSource; + * CallbackTraceSource 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 ("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 + * MyModel::GetTraceResolver (void) const + * { + * // create an empty trace resolver + * Ptr resolver = Create (); + * // 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 + */ diff --git a/samples/main-random-topology.cc b/samples/main-random-topology.cc index 3fb52a0d9..3021ed3fb 100644 --- a/samples/main-random-topology.cc +++ b/samples/main-random-topology.cc @@ -15,7 +15,7 @@ using namespace ns3; static void -CourseChange (Ptr position) +CourseChange (const TraceContext &context, Ptr 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 notifier = Create (); - notifier->RegisterListener (MakeCallback (&CourseChange)); + notifier->TraceConnect ("/course-change", MakeCallback (&CourseChange)); objects.push_back (notifier); } diff --git a/src/common/array-trace-resolver.h b/src/common/array-trace-resolver.h deleted file mode 100644 index e4507d4af..000000000 --- a/src/common/array-trace-resolver.h +++ /dev/null @@ -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 - */ -#ifndef ARRAY_TRACE_RESOLVER_H -#define ARRAY_TRACE_RESOLVER_H - -#include -#include -#include "ns3/callback.h" -#include "trace-resolver.h" - -namespace ns3 { - -/** - * \brief a helper class to offer trace resolution for an array of objects. - * \ingroup lowleveltracing - */ -template -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 getSize, - Callback get); -private: - virtual TraceResolverList DoLookup (std::string id) const; - Callback m_getSize; - Callback m_get; -}; -}//namespace ns3 - -namespace ns3 { - -template -ArrayTraceResolver::ArrayTraceResolver (TraceContext const &context, - Callback getSize, - Callback get) - : TraceResolver (context), - m_getSize (getSize), - m_get (get) -{} -template -TraceResolver::TraceResolverList -ArrayTraceResolver::DoLookup (std::string id) const -{ - TraceResolverList list; - if (id == "*") - { - for (uint32_t i = 0; i < m_getSize (); i++) - { - TraceContext context = GetContext (); - INDEX index = i; - context.Add (index); - list.push_back (m_get (i)->CreateTraceResolver (context)); - } - } - return list; -} - - -}//namespace ns3 - -#endif /* ARRAY_TRACE_RESOLVER_H */ diff --git a/src/common/callback-trace-source.h b/src/common/callback-trace-source.h deleted file mode 100644 index a1e13df9d..000000000 --- a/src/common/callback-trace-source.h +++ /dev/null @@ -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 - */ - -#ifndef CALLBACK_TRACE_H -#define CALLBACK_TRACE_H - -#include -#include "ns3/callback.h" -#include "ns3/fatal-error.h" -#include "trace-context.h" - -namespace ns3 { - - -/** - * \brief log arbitrary number of parameters to a matching ns3::Callback - * \ingroup lowleveltracing - * - * Whenever operator () is invoked on this class, the call and its arguments - * are forwarded to the internal matching ns3::Callback. - */ -template -class CallbackTraceSource { -public: - CallbackTraceSource (); - void AddCallback (CallbackBase const & callback, TraceContext const & context); - void RemoveCallback (CallbackBase const & callback); - void operator() (void); - void operator() (T1 a1); - void operator() (T1 a1, T2 a2); - void operator() (T1 a1, T2 a2, T3 a3); - void operator() (T1 a1, T2 a2, T3 a3, T4 a4); - -private: - typedef std::list > CallbackList; - TraceContext m_context; - CallbackList m_callbackList; -}; - -}; // namespace ns3 - -// implementation below. - -namespace ns3 { - -template -CallbackTraceSource::CallbackTraceSource () - : m_callbackList () -{} -template -void -CallbackTraceSource::AddCallback (CallbackBase const & callback, - TraceContext const &context) -{ - Callback cb; - cb.Assign (callback); - m_context.Add (context); - m_callbackList.push_back (cb); -} -template -void -CallbackTraceSource::RemoveCallback (CallbackBase const & callback) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); /* empty */) - { - if ((*i).IsEqual (callback)) - { - i = m_callbackList.erase (i); - } - else - { - i++; - } - } -} -template -void -CallbackTraceSource::operator() (void) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context); - } -} -template -void -CallbackTraceSource::operator() (T1 a1) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1); - } -} -template -void -CallbackTraceSource::operator() (T1 a1, T2 a2) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1, a2); - } -} -template -void -CallbackTraceSource::operator() (T1 a1, T2 a2, T3 a3) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1, a2, a3); - } -} -template -void -CallbackTraceSource::operator() (T1 a1, T2 a2, T3 a3, T4 a4) -{ - for (typename CallbackList::iterator i = m_callbackList.begin (); - i != m_callbackList.end (); i++) - { - (*i) (m_context, a1, a2, a3, a4); - } -} - -}//namespace ns3 - -#endif /* CALLBACK_TRACE_H */ diff --git a/src/common/composite-trace-resolver.cc b/src/common/composite-trace-resolver.cc deleted file mode 100644 index bf60aa81e..000000000 --- a/src/common/composite-trace-resolver.cc +++ /dev/null @@ -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 - */ -#include "composite-trace-resolver.h" - -namespace ns3 { - -CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context) - : TraceResolver (context) -{} - -CompositeTraceResolver::~CompositeTraceResolver () -{} - -void -CompositeTraceResolver::Add (std::string name, - Callback createResolver) -{ - TraceContext traceContext = GetContext (); - DoAdd (name, createResolver, traceContext); -} - -void -CompositeTraceResolver::DoAdd (std::string name, - Callback createResolver, - TraceContext const &context) -{ - struct CallbackTraceSourceItem item; - item.name = name; - item.createResolver = createResolver; - item.context = context; - m_items.push_back (item); -} - -TraceResolver::TraceResolverList -CompositeTraceResolver::DoLookup (std::string id) const -{ - if (id == "*") - { - TraceResolver::TraceResolverList list; - for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) - { - list.push_back (i->createResolver (i->context)); - } - return list; - } - std::string::size_type start, end; - start = id.find_first_of ("(", 0); - end = id.find_first_of (")", 0); - if (start != 0 || end != (id.size ()-1)) - { - for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++) - { - if (i->name == id) - { - TraceResolver::TraceResolverList list; - list.push_back (i->createResolver (i->context)); - return list; - } - } - } - std::list names; - std::string alternatives = std::string (id, start+1, end-1); - std::string::size_type next, cur; - next = 0; - cur = 0; - while (true) - { - std::string element; - next = alternatives.find ("|", cur); - if (next == std::string::npos) - { - element = std::string (alternatives, cur, alternatives.size ()); - names.push_back (element); - break; - } - element = std::string (alternatives, cur, next); - names.push_back (element); - cur = next + 1; - } - TraceResolver::TraceResolverList list; - for (std::list::const_iterator i = names.begin (); i != names.end (); i++) - { - for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++) - { - if (j->name == *i) - { - list.push_back (j->createResolver (j->context)); - break; - } - } - } - return list; -} - -}//namespace ns3 - -#ifdef RUN_SELF_TESTS - -#include "ns3/test.h" -#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"); 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"); 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 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 traceDoubleA; - CallbackTraceSource 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 */ diff --git a/src/common/composite-trace-resolver.h b/src/common/composite-trace-resolver.h deleted file mode 100644 index cadf9da2d..000000000 --- a/src/common/composite-trace-resolver.h +++ /dev/null @@ -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 - */ -#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 - void Add (std::string name, - CallbackTraceSource &trace, T const &context); - /** - * \param name name of trace source - * \param trace a signed variable trace source - * \param context the context associated to this trace source - * - * Add a signed variable trace source in this resolver. - * This trace source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - SVTraceSource &trace, T const &context); - /** - * \param name name of trace source - * \param trace an unsigned variable trace source - * \param context the context associated to this trace source - * - * Add an unsigned variable trace source in this resolver. - * This trace source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - UVTraceSource &trace, T const &context); - /** - * \param name name of trace source - * \param trace a floating-point variable trace source - * \param context the context associated to this trace source - * - * Add a floating-point variable trace source in this resolver. - * This trace source will match the name specified during namespace - * resolution. The TraceContext of this trace source will also - * be automatically extended to contain the input context. - */ - template - void Add (std::string name, - FVTraceSource &trace, T const &context); - - /** - * \param name name of child trace resolver - * \param createResolver a trace resolver constructor - * \param context the context associated to this entry - * - * Add a child trace resolver to this resolver. This child - * trace resolver will match the name specified during - * namespace resolution. When this happens, the constructor - * will be invoked to create the child trace resolver and - * the associated TraceContext will be automatically extended - * to contain the input context. - */ - template - void Add (std::string name, - Callback createResolver, - T const &context); - - /** - * \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 createResolver); -private: - template - void DoAddTraceSource (std::string name, - SOURCE &traceSource, CONTEXT const &context); - template - static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace, - TraceContext const &context); - void DoAdd (std::string name, - Callback createResolver, - TraceContext const &context); - virtual TraceResolverList DoLookup (std::string id) const; - - struct CallbackTraceSourceItem - { - std::string name; - Callback createResolver; - TraceContext context; - }; - - typedef std::list TraceItems; - TraceItems m_items; -}; - -}//namespace ns3 - -namespace ns3 { - -template -void -CompositeTraceResolver::DoAddTraceSource (std::string name, - SOURCE &traceSource, CONTEXT const &context) -{ - TraceContext traceContext = GetContext (); - traceContext.Add (context); - TraceResolver *(*create) (SOURCE *trace, TraceContext const &context); - create = &CompositeTraceResolver::CreateTerminalTraceResolver; - Callback createResolver = - MakeBoundCallback (create, &traceSource); - DoAdd (name, createResolver, traceContext); -} - -template -TraceResolver * -CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource, - TraceContext const &context) -{ - return new TerminalTraceResolver (*traceSource, context); -} - - - - -template -void -CompositeTraceResolver::Add (std::string name, - CallbackTraceSource &trace, - T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - SVTraceSource &trace, T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - UVTraceSource &trace, T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - FVTraceSource &trace, T const &context) -{ - DoAddTraceSource (name, trace, context); -} -template -void -CompositeTraceResolver::Add (std::string name, - Callback createResolver, - T const &context) -{ - TraceContext traceContext = GetContext (); - traceContext.Add (context); - DoAdd (name, createResolver, traceContext); -} - -}//namespace ns3 - -#endif /* COMPOSITE_TRACE_RESOLVER_H */ diff --git a/src/common/empty-trace-resolver.h b/src/common/empty-trace-resolver.h deleted file mode 100644 index 04f1c1bc4..000000000 --- a/src/common/empty-trace-resolver.h +++ /dev/null @@ -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 - */ -#ifndef EMPTY_TRACE_RESOLVER_H -#define EMPTY_TRACE_RESOLVER_H - -#include "trace-resolver.h" - -namespace ns3 { - -class TraceContext; - -/** - * \brief a TraceResolver instance which does not resolve anything. - * \ingroup tracing - * - * Trying to resolve against this class will yield no matches and no - * connections. Returning an instance of this class from a - * CreateTraceResolver method is a hand way of not implementing - * any Tracing code. - */ -class EmptyTraceResolver : public TraceResolver -{ -public: - /** - * \param o necessary context for this class. - * - * The only constructor exported by this class. - */ - EmptyTraceResolver (TraceContext const &o); -}; - -}//namespace ns3 - -#endif /* EMPTY_TRACE_RESOLVER_H */ diff --git a/src/common/packet.cc b/src/common/packet.cc index 5159f3e2c..0de766dba 100644 --- a/src/common/packet.cc +++ b/src/common/packet.cc @@ -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 diff --git a/src/common/packet.h b/src/common/packet.h index 00c540600..f1e14cf02 100644 --- a/src/common/packet.h +++ b/src/common/packet.h @@ -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 diff --git a/src/common/terminal-trace-resolver.h b/src/common/terminal-trace-resolver.h deleted file mode 100644 index e026d07cb..000000000 --- a/src/common/terminal-trace-resolver.h +++ /dev/null @@ -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 - */ -#ifndef TERMINAL_TRACE_RESOLVER_H -#define TERMINAL_TRACE_RESOLVER_H - -#include "trace-resolver.h" - -namespace ns3 { - -class TraceContext; - -template -class TerminalTraceResolver : public TraceResolver -{ - public: - TerminalTraceResolver (T &traceSource, TraceContext const &context); - private: - virtual void DoConnect (CallbackBase const &cb); - virtual void DoDisconnect (CallbackBase const &cb); - T &m_traceSource; -}; - -}//namespace ns3 - -namespace ns3 { - -template -TerminalTraceResolver::TerminalTraceResolver (T &traceSource, - TraceContext const &context) - : TraceResolver (context), - m_traceSource (traceSource) -{} -template -void -TerminalTraceResolver::DoConnect (CallbackBase const &cb) -{ - m_traceSource.AddCallback (cb, GetContext ()); -} -template -void -TerminalTraceResolver::DoDisconnect (CallbackBase const &cb) -{ - m_traceSource.RemoveCallback (cb); -} - -}//namespace ns3 - -#endif /* TERMINAL_TRACE_RESOLVER_H */ diff --git a/src/common/trace-resolver.cc b/src/common/trace-resolver.cc deleted file mode 100644 index 251e7cc87..000000000 --- a/src/common/trace-resolver.cc +++ /dev/null @@ -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 - */ -#include "trace-resolver.h" - -namespace ns3 { - -TraceResolver::TraceResolver (TraceContext const &context) - : m_context (context) -{} - -TraceResolver::~TraceResolver () -{} - -TraceContext const & -TraceResolver::GetContext (void) const -{ - return m_context; -} - -void -TraceResolver::Connect (std::string path, CallbackBase const &cb) -{ - std::string::size_type cur = 1; - // check that first char is "/" - std::string::size_type next = path.find ("/", cur); - std::string element = std::string (path, cur, next-1); - TraceResolverList resolverList = DoLookup (element); - for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++) - { - TraceResolver *resolver = *i; - if (next == std::string::npos) - { - // we really break the recursion here. - resolver->DoConnect (cb); - } - else - { - std::string subpath = std::string (path, next, std::string::npos); - resolver->Connect (subpath, cb); - } - delete resolver; - } - resolverList.erase (resolverList.begin (), resolverList.end ()); -} - -void -TraceResolver::Disconnect (std::string path, CallbackBase const &cb) -{ - std::string::size_type cur = 1; - // check that first char is "/" - std::string::size_type next = path.find ("/", cur); - std::string element = std::string (path, cur, next-1); - TraceResolverList resolverList = DoLookup (element); - for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++) - { - TraceResolver *resolver = *i; - if (next == std::string::npos) - { - // we really break the recursion here. - resolver->DoDisconnect (cb); - } - else - { - std::string subpath = std::string (path, next, std::string::npos); - resolver->Disconnect (subpath, cb); - } - delete resolver; - } - resolverList.erase (resolverList.begin (), resolverList.end ()); -} - -TraceResolver::TraceResolverList -TraceResolver::DoLookup (std::string id) const -{ - return TraceResolverList (); -} -void -TraceResolver::DoConnect (CallbackBase const &cb) -{} - -void -TraceResolver::DoDisconnect (CallbackBase const &cb) -{} - - -}//namespace ns3 diff --git a/src/common/trace-resolver.h b/src/common/trace-resolver.h deleted file mode 100644 index 93bf43095..000000000 --- a/src/common/trace-resolver.h +++ /dev/null @@ -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 - */ -#ifndef TRACE_RESOLVER_H -#define TRACE_RESOLVER_H - -#include -#include -#include "trace-context.h" - -namespace ns3 { - -class CallbackBase; - -/** - * \brief the base class which is used to incremental perform trace - * namespace resolution. - * \ingroup 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 TraceResolverList; -private: - TraceResolver (); - /** - * \param id the id to resolve. This is supposed to be - * one element of the global tracing namespace. - * \returns a list of reslvers which match the input namespace element - * - * A subclass which overrides this method should return a potentially - * empty list of pointers to ns3::TraceResolver instances which match - * the input namespace element. Each of these TraceResolver should be - * instanciated with a TraceContext which holds enough context - * information to identify the type of the TraceResolver. - */ - virtual TraceResolverList DoLookup (std::string id) const; - /** - * \param cb callback to connect - * - * This method is invoked on leaf trace resolvers. - */ - virtual void DoConnect (CallbackBase const &cb); - /** - * \param cb callback to disconnect - * - * This method is invoked on leaf trace resolvers. - */ - virtual void DoDisconnect (CallbackBase const &cb); - TraceContext m_context; -}; - -}//namespace ns3 - -#endif /* TRACE_RESOLVER_H */ diff --git a/src/common/trace-root.cc b/src/common/trace-root.cc deleted file mode 100644 index 5bb270b8c..000000000 --- a/src/common/trace-root.cc +++ /dev/null @@ -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 - */ -#include "trace-root.h" -#include "ns3/composite-trace-resolver.h" -#include "ns3/trace-context.h" - -namespace ns3 { - -void -TraceRoot::Connect (std::string path, CallbackBase const &cb) -{ - TraceResolver *resolver = GetComposite (); - resolver->Connect (path, cb); -} -void -TraceRoot::Disconnect (std::string path, CallbackBase const &cb) -{ - TraceResolver *resolver = GetComposite (); - resolver->Disconnect (path, cb); -} -void -TraceRoot::Register (std::string name, - Callback createResolver) -{ - CompositeTraceResolver *resolver = GetComposite (); - resolver->Add (name, createResolver); -} - -CompositeTraceResolver * -TraceRoot::GetComposite (void) -{ - static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ()); - return &resolver; -} - -} // namespace ns3 diff --git a/src/common/trace-root.h b/src/common/trace-root.h deleted file mode 100644 index a07f923cd..000000000 --- a/src/common/trace-root.h +++ /dev/null @@ -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 - */ -#ifndef TRACE_ROOT_H -#define TRACE_ROOT_H - -#include -#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 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 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 createResolver); -private: - static CompositeTraceResolver *GetComposite (void); -}; - -}// namespace ns3 - -#endif /* TRACE_ROOT_H */ diff --git a/src/common/wscript b/src/common/wscript index c6e9cb45d..2472ecd1e 100644 --- a/src/common/wscript +++ b/src/common/wscript @@ -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', ] diff --git a/src/core/array-trace-resolver.h b/src/core/array-trace-resolver.h new file mode 100644 index 000000000..ecbc63d5d --- /dev/null +++ b/src/core/array-trace-resolver.h @@ -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 + */ +#ifndef ARRAY_TRACE_RESOLVER_H +#define ARRAY_TRACE_RESOLVER_H + +#include +#include +#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 +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 + 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 Get (void) = 0; + virtual void Rewind (void) = 0; + }; + IteratorBase *m_iter; +}; +}//namespace ns3 + + +// implementation +namespace ns3 { + +template +ArrayTraceResolver::ArrayTraceResolver () + : m_iter (0) +{} + +template +ArrayTraceResolver::~ArrayTraceResolver () +{ + delete m_iter; +} + +template +template +void +ArrayTraceResolver::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 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 +void +ArrayTraceResolver::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 obj = m_iter->Get (); + obj->GetTraceResolver ()->Connect (subpath, cb, tmp); + j++; + } + } +} +template +void +ArrayTraceResolver::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 obj = m_iter->Get (); + obj->TraceDisconnect (subpath, cb); + } + } +} +template +void +ArrayTraceResolver::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 obj = m_iter->Get (); + obj->GetTraceResolver ()->CollectSources (path, tmp, collection); + j++; + } +} + +template +void +ArrayTraceResolver::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 obj = m_iter->Get (); + obj->GetTraceResolver ()->TraceAll (os, tmp); + j++; + } +} + +}//namespace ns3 + +#endif /* ARRAY_TRACE_RESOLVER_H */ diff --git a/src/core/callback-test.cc b/src/core/callback-test.cc index 9e8cf259f..4fb062321 100644 --- a/src/core/callback-test.cc +++ b/src/core/callback-test.cc @@ -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 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 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; } diff --git a/src/common/callback-trace-source.cc b/src/core/callback-trace-source.cc similarity index 80% rename from src/common/callback-trace-source.cc rename to src/core/callback-trace-source.cc index d35b4f860..02298520e 100644 --- a/src/common/callback-trace-source.cc +++ b/src/core/callback-trace-source.cc @@ -19,7 +19,10 @@ * Author: Mathieu Lacage */ #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 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 */ diff --git a/src/core/callback-trace-source.h b/src/core/callback-trace-source.h new file mode 100644 index 000000000..2e302cdc2 --- /dev/null +++ b/src/core/callback-trace-source.h @@ -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 + */ + +#ifndef CALLBACK_TRACE_H +#define CALLBACK_TRACE_H + +#include +#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 +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 > CallbackList; + TraceContext m_context; + CallbackList m_callbackList; +}; + +}; // namespace ns3 + +// implementation below. + +namespace ns3 { + +namespace internal { + +template +class TraceSinkPrint; + +template +class TraceSinkPrint +{ +public: + static Callback 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 +class TraceSinkPrint +{ +public: + static Callback 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 +class TraceSinkPrint +{ +public: + static Callback 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 +class TraceSinkPrint +{ +public: + static Callback 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 +{ +public: + static Callback 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 +CallbackTraceSource::CallbackTraceSource () + : m_callbackList () +{} +template +void +CallbackTraceSource::AddCallback (CallbackBase const & callback, + TraceContext const &context) +{ + Callback cb; + cb.Assign (callback); + m_context.Union (context); + m_callbackList.push_back (cb); +} +template +void +CallbackTraceSource::RemoveCallback (CallbackBase const & callback) +{ + for (typename CallbackList::iterator i = m_callbackList.begin (); + i != m_callbackList.end (); /* empty */) + { + if ((*i).IsEqual (callback)) + { + i = m_callbackList.erase (i); + } + else + { + i++; + } + } +} +template +void +CallbackTraceSource::ConnectPrinter (std::ostream &os, const TraceContext &context) +{ + AddCallback (ns3::internal::TraceSinkPrint::Make (os), context); +} +template +void +CallbackTraceSource::operator() (void) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context); + } +} +template +void +CallbackTraceSource::operator() (T1 a1) const +{ + for (typename CallbackList::const_iterator i = m_callbackList.begin (); + i != m_callbackList.end (); i++) + { + (*i) (m_context, a1); + } +} +template +void +CallbackTraceSource::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 +void +CallbackTraceSource::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 +void +CallbackTraceSource::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 */ diff --git a/src/core/callback.h b/src/core/callback.h index 94e58ca92..ff04de447 100644 --- a/src/core/callback.h +++ b/src/core/callback.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 +template class CallbackImpl; // define CallbackImpl for 0 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (void) = 0; }; // define CallbackImpl for 1 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1) = 0; }; // define CallbackImpl for 2 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2) = 0; }; // define CallbackImpl for 3 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2, T3) = 0; }; // define CallbackImpl for 4 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2, T3, T4) = 0; }; // define CallbackImpl for 5 params template -class CallbackImpl : public CallbackImplBase { +class CallbackImpl : public CallbackImplBase { public: virtual ~CallbackImpl () {} virtual R operator() (T1, T2, T3, T4, T5) = 0; }; +// define CallbackImpl for 6 params + template +class CallbackImpl : public CallbackImplBase { +public: + virtual ~CallbackImpl () {} + virtual R operator() (T1, T2, T3, T4, T5, T6) = 0; +}; // an impl for Functors: -template -class FunctorCallbackImpl : public CallbackImpl { +template +class FunctorCallbackImpl : public CallbackImpl { 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 const *otherDerived = - dynamic_cast const *> (other); + FunctorCallbackImpl const *otherDerived = + dynamic_cast const *> (other); if (otherDerived == 0) { return false; @@ -178,8 +189,8 @@ private: }; // an impl for pointer to member functions -template -class MemPtrCallbackImpl : public CallbackImpl { +template +class MemPtrCallbackImpl : public CallbackImpl { 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::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::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5, a6); + } virtual bool IsEqual (CallbackImplBase const *other) const { - MemPtrCallbackImpl const *otherDerived = - dynamic_cast const *> (other); + MemPtrCallbackImpl const *otherDerived = + dynamic_cast const *> (other); if (otherDerived == 0) { return false; @@ -260,22 +274,22 @@ public: template + 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 Callback (FUNCTOR const &functor, bool, bool) - : m_impl (Create > (functor)) + : m_impl (Create > (functor)) {} template Callback (OBJ_PTR const &objPtr, MEM_PTR mem_ptr) - : m_impl (Create > (objPtr, mem_ptr)) + : m_impl (Create > (objPtr, mem_ptr)) {} - Callback (Ptr > const &impl) + Callback (Ptr > 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 *> (otherBase) != 0) + if (dynamic_cast *> (otherBase) != 0) { return true; } @@ -328,27 +345,27 @@ public: " got=" << typeid (other).name () << ", expected=" << typeid (*this).name ()); } - const Callback *goodType = static_cast *> (&other); + const Callback *goodType = static_cast *> (&other); *this = *goodType; } void Assign (Ptr other) { - CallbackImpl *impl = dynamic_cast *> (PeekPointer (other)); + CallbackImpl *impl = dynamic_cast *> (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 (impl); + *this = Callback (impl); } virtual PtrGetImpl (void) const { return m_impl; } private: - virtual CallbackImpl *PeekImpl (void) const { + virtual CallbackImpl *PeekImpl (void) const { return PeekPointer (m_impl); } - Ptr > m_impl; + Ptr > m_impl; }; /** @@ -369,7 +386,7 @@ Callback MakeCallback (R (T::*memPtr) (void), OBJ objPtr) { return Callback (objPtr, memPtr); } template -Callback MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) () const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -381,11 +398,11 @@ Callback MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) { * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -397,11 +414,11 @@ Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -413,11 +430,11 @@ Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const o * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -429,11 +446,11 @@ Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*c * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -445,13 +462,29 @@ Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ c * and potentially return a value. */ template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ objPtr) { return Callback (objPtr, mem_ptr); } template -Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) { +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ objPtr) { return Callback (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 +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5,T6), OBJ objPtr) { + return Callback (objPtr, mem_ptr); +} +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5,T6) const, OBJ objPtr) { + return Callback (objPtr, mem_ptr); +} /** * \ingroup MakeCallback @@ -519,6 +552,17 @@ template MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) { return Callback (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 +Callback MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5,T6)) { + return Callback (fnPtr, true, true); +} @@ -587,6 +631,17 @@ template MakeNullCallback (void) { return Callback (); } +/** + * \ingroup MakeCallback + * \overload Callback MakeNullCallback (void) + * \return a wrapper Callback + * Build a null callback which takes five arguments + * and potentially return a value. + */ +template +Callback MakeNullCallback (void) { + return Callback (); +} /* @@ -596,9 +651,10 @@ Callback MakeNullCallback (void) { */ // an impl for Bound Functors: template -class BoundFunctorCallbackImpl : public CallbackImpl { +class BoundFunctorCallbackImpl : public CallbackImpl { public: - BoundFunctorCallbackImpl (T const &functor, TX a) + template + 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::ReferencedType m_a; }; -template -Callback MakeBoundCallback (R (*fnPtr) (TX), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX), ARG a) { + Ptr > impl = Create >(fnPtr, a); return Callback (impl); } -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3), ARG a) { + Ptr > impl = + Create > (fnPtr, a); + return Callback (impl); +} +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } - -template -Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), TX a) { - Ptr > impl = +template +Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), ARG a) { + Ptr > impl = Create > (fnPtr, a); return Callback (impl); } diff --git a/src/core/composite-trace-resolver.cc b/src/core/composite-trace-resolver.cc new file mode 100644 index 000000000..bf59054f2 --- /dev/null +++ b/src/core/composite-trace-resolver.cc @@ -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 + */ +#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 > 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 > 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 (&trace); + item->doc = doc; + AddItem (item); +} + + + + +void +CompositeTraceResolver::AddComposite (std::string name, Ptr composite) +{ + DoAddComposite (name, composite, TraceContext ()); +} +void +CompositeTraceResolver::DoAddComposite (std::string name, Ptr 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 composite; + } *item = new CompositeResolveItem (); + item->name = name; + item->context = context; + item->composite = composite; + AddItem (item); +} + +void +CompositeTraceResolver::SetParentResolver (Ptr resolver) +{ + m_parent = resolver; +} + +void +CompositeTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context) +{ + NS_DEBUG ("connect path="<name == id) + { + operation.Do (subpath, *i); + operation.DoParent (path, m_parent); + return; + } + } + } + std::list 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::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="<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"); 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"); 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 CreateSubResolver (); + + + bool m_gotDoubleA; + bool m_gotDoubleB; + CallbackTraceSource m_traceInt; + bool m_gotInt; +}; + +CompositeTraceResolverTest::CompositeTraceResolverTest () + : Test ("CompositeTraceResolver") +{} +CompositeTraceResolverTest::~CompositeTraceResolverTest () +{} +void +CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v) +{ + 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 +CompositeTraceResolverTest::CreateSubResolver (void) +{ + Ptr subresolver = Create (); + subresolver->AddSource ("trace-int", TraceDoc ("test source"), m_traceInt, + SubTraceSourceTest (SubTraceSourceTest::INT)); + return subresolver; +} +bool +CompositeTraceResolverTest::RunTests (void) +{ + bool ok = true; + + CallbackTraceSource traceDoubleA; + CallbackTraceSource 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 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 */ diff --git a/src/core/composite-trace-resolver.h b/src/core/composite-trace-resolver.h new file mode 100644 index 000000000..ceca4044a --- /dev/null +++ b/src/core/composite-trace-resolver.h @@ -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 + */ +#ifndef COMPOSITE_TRACE_RESOLVER_H +#define COMPOSITE_TRACE_RESOLVER_H + +#include +#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 + 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 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 + void AddComposite (std::string name, Ptr 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 + 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 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 TraceItems; + class Operation + { + public: + virtual ~Operation () {} + virtual void Do (std::string subpath, ResolveItem *item) const = 0; + virtual void DoParent (std::string path, Ptr 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 composite, const TraceContext &context); + void DoAddSource (std::string name, + const TraceDoc &doc, + const TraceSource &trace, + const TraceContext &context); + void Add (std::string name, + Callback > createResolver); + + + CompositeTraceResolver::TraceItems m_items; + Ptr m_parent; +}; + +}//namespace ns3 + +namespace ns3 { + + + +template +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 +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 > array; + } *item = new ArrayResolveItem (); + item->name = name; + item->context = TraceContext (); + item->array = Create > (); + item->array->SetIterators (begin, end); + AddItem (item); +} + +template +void +CompositeTraceResolver::AddComposite (std::string name, Ptr composite, const T &contextElement) +{ + TraceContext context; + context.AddElement (contextElement); + DoAddComposite (name, composite, context); +} + + + +}//namespace ns3 + +#endif /* COMPOSITE_TRACE_RESOLVER_H */ diff --git a/src/common/fv-trace-source.h b/src/core/fv-trace-source.h similarity index 82% rename from src/common/fv-trace-source.h rename to src/core/fv-trace-source.h index 2e059303b..c0f816dbb 100644 --- a/src/common/fv-trace-source.h +++ b/src/core/fv-trace-source.h @@ -23,11 +23,12 @@ #define F_VARIABLE_TRACER_H #include "callback-trace-source.h" +#include "trace-source.h" #include namespace ns3 { -class FVTraceSourceBase { +class FVTraceSourceBase : public TraceSource { public: typedef CallbackTraceSource 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) diff --git a/src/core/object.cc b/src/core/object.cc index 9b4812c42..27ac31917 100644 --- a/src/core/object.cc +++ b/src/core/object.cc @@ -22,8 +22,12 @@ #include "assert.h" #include "singleton.h" #include "uid-manager.h" +#include "trace-resolver.h" +#include "debug.h" #include +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 m_parents; }; @@ -55,6 +60,68 @@ IidTree::LookupParent (uint16_t child) namespace ns3 { +class InterfaceIdTraceResolver : public TraceResolver +{ +public: + InterfaceIdTraceResolver (Ptr 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 ParseForInterface (std::string path); + Ptr m_aggregate; +}; + +InterfaceIdTraceResolver::InterfaceIdTraceResolver (Ptr aggregate) + : m_aggregate (aggregate) +{} +Ptr +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 interface = m_aggregate->QueryInterface (interfaceId); + return interface; +} +void +InterfaceIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context) +{ + Ptr interface = ParseForInterface (path); + if (interface != 0) + { + interface->GetTraceResolver ()->Connect (GetSubpath (path), cb, context); + } +} +void +InterfaceIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb) +{ + Ptr 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::Get ()->LookupParent (iid.m_iid); } +std::string +InterfaceId::GetName (void) const +{ + std::string name = Singleton::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 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 +Object::GetTraceResolver (void) const +{ + Ptr resolver = + Create (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 GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("basea-x", ns3::TraceDoc ("test source"), m_source); + resolver->SetParentResolver (Object::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource 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 GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("deriveda-x", ns3::TraceDoc ("test source"), m_sourceDerived); + resolver->SetParentResolver (BaseA::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource 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 GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("baseb-x", ns3::TraceDoc ("test source"), m_source); + resolver->SetParentResolver (Object::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource 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 GetTraceResolver (void) const + { + ns3::Ptr resolver = + ns3::Create (); + resolver->AddSource ("derivedb-x", ns3::TraceDoc ("test source"), m_sourceDerived); + resolver->SetParentResolver (BaseB::GetTraceResolver ()); + return resolver; + } + ns3::SVTraceSource 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 = Create (); - if (baseA->QueryInterface (BaseA::iid) != baseA) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (BaseA::iid), baseA); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), 0); baseA = Create (10); - if (baseA->QueryInterface (BaseA::iid) != baseA) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != baseA) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) == 0) - { - ok = false; - } + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (BaseA::iid), baseA); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), baseA); + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (DerivedA::iid), 0); baseA = Create (); Ptr baseB = Create (); Ptr baseBCopy = baseB; baseA->AddInterface (baseB); - if (baseA->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseA->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } - if (baseA->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } - if (baseA->QueryInterface (DerivedB::iid) != 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedB::iid) != 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedA::iid) != 0) - { - ok = false; - } - if (baseBCopy->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (BaseB::iid), 0); + NS_TEST_ASSERT_EQUAL (baseA->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseB::iid), 0); + NS_TEST_ASSERT_EQUAL (baseB->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_EQUAL (baseB->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface (BaseA::iid), 0); baseA = Create (1); baseB = Create (1); baseBCopy = baseB; baseA->AddInterface (baseB); - if (baseA->QueryInterface (DerivedB::iid) == 0) - { - ok = false; - } - if (baseA->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedA::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseBCopy->QueryInterface (DerivedA::iid) == 0) - { - ok = false; - } - if (baseBCopy->QueryInterface (BaseA::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (DerivedB::iid) == 0) - { - ok = false; - } - if (baseB->QueryInterface (BaseB::iid) == 0) - { - ok = false; - } + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface (BaseB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface (DerivedA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface (BaseA::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (DerivedB::iid), 0); + NS_TEST_ASSERT_UNEQUAL (baseB->QueryInterface (BaseB::iid), 0) baseA = Create (); baseB = Create (); @@ -406,7 +570,76 @@ ObjectTest::RunTests (void) baseA = 0; baseA = baseB->QueryInterface (BaseA::iid); - return ok; + baseA = Create (); + 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->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 = Create (1); + baseB = Create (); + 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; diff --git a/src/core/object.h b/src/core/object.h index d45d7f67c..36aa3a384 100644 --- a/src/core/object.h +++ b/src/core/object.h @@ -24,9 +24,13 @@ #include #include #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 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 GetTraceResolver (void) const; protected: /** * \param iid an InterfaceId @@ -147,12 +180,17 @@ protected: */ virtual void DoDispose (void); private: + friend class InterfaceIdTraceResolver; Ptr 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; }; diff --git a/src/core/random-variable-default-value.cc b/src/core/random-variable-default-value.cc index 3217c3513..14fdfa5a3 100644 --- a/src/core/random-variable-default-value.cc +++ b/src/core/random-variable-default-value.cc @@ -19,7 +19,7 @@ * Author: Mathieu Lacage */ #include "random-variable-default-value.h" -#include "ns3/debug.h" +#include "debug.h" NS_DEBUG_COMPONENT_DEFINE ("RandomVariableDefaultValue"); diff --git a/src/common/stream-tracer-test.cc b/src/core/stream-tracer-test.cc similarity index 98% rename from src/common/stream-tracer-test.cc rename to src/core/stream-tracer-test.cc index f38e80dc4..f708015b6 100644 --- a/src/common/stream-tracer-test.cc +++ b/src/core/stream-tracer-test.cc @@ -19,7 +19,7 @@ * Author: Mathieu Lacage */ #include "stream-tracer.h" -#include "ns3/test.h" +#include "test.h" #include #ifdef RUN_SELF_TESTS diff --git a/src/common/stream-tracer.h b/src/core/stream-tracer.h similarity index 100% rename from src/common/stream-tracer.h rename to src/core/stream-tracer.h diff --git a/src/common/sv-trace-source.h b/src/core/sv-trace-source.h similarity index 93% rename from src/common/sv-trace-source.h rename to src/core/sv-trace-source.h index ce5511705..8cbb2447b 100644 --- a/src/common/sv-trace-source.h +++ b/src/core/sv-trace-source.h @@ -23,11 +23,12 @@ #define SV_TRACE_SOURCE_H #include "callback-trace-source.h" +#include "trace-source.h" #include namespace ns3 { -class SVTraceSourceBase { +class SVTraceSourceBase : public TraceSource { public: typedef CallbackTraceSource 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 : \code #include - #include "ns3/sv-trace-source.h" + #include "sv-trace-source.h" ns3::SVTraceSource var; \endcode diff --git a/src/core/test.h b/src/core/test.h index 356c08ee2..809c44f0d 100644 --- a/src/core/test.h +++ b/src/core/test.h @@ -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 diff --git a/src/common/trace-context-element.cc b/src/core/trace-context-element.cc similarity index 80% rename from src/common/trace-context-element.cc rename to src/core/trace-context-element.cc index 838250af8..dee4e97f4 100644 --- a/src/common/trace-context-element.cc +++ b/src/core/trace-context-element.cc @@ -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) { diff --git a/src/common/trace-context-element.h b/src/core/trace-context-element.h similarity index 87% rename from src/common/trace-context-element.h rename to src/core/trace-context-element.h index e1c36c4d9..aba7c2598 100644 --- a/src/common/trace-context-element.h +++ b/src/core/trace-context-element.h @@ -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 InfoVector; static InfoVector *GetInfoVector (void); template + static std::string DoGetTypeName (void); + template static void DoPrint (uint8_t *instance, std::ostream &os); template static void DoDestroy (uint8_t *instance); @@ -143,6 +157,13 @@ ElementRegistry::DoPrint (uint8_t *instance, std::ostream &os) obj.Print (os); } template +std::string +ElementRegistry::DoGetTypeName (void) +{ + static T obj; + return obj.GetTypeName (); +} +template 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; info.print = &ElementRegistry::DoPrint; info.destroy = &ElementRegistry::DoDestroy; vec->push_back (info); diff --git a/src/common/trace-context.cc b/src/core/trace-context.cc similarity index 65% rename from src/common/trace-context.cc rename to src/core/trace-context.cc index 50e9d0a73..af3ac2cfa 100644 --- a/src/common/trace-context.cc +++ b/src/core/trace-context.cc @@ -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 namespace ns3 { @@ -242,8 +371,8 @@ template class Ctx : public TraceContextElement { public: - static uint16_t GetUid (void) {static uint16_t uid = AllocateUid > (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 > (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; } diff --git a/src/common/trace-context.h b/src/core/trace-context.h similarity index 65% rename from src/common/trace-context.h rename to src/core/trace-context.h index eee3c960c..908f3ecb9 100644 --- a/src/common/trace-context.h +++ b/src/core/trace-context.h @@ -23,26 +23,28 @@ #include #include -#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 - 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 - 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 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 -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 bool diff --git a/src/core/trace-doc.cc b/src/core/trace-doc.cc new file mode 100644 index 000000000..b41089d10 --- /dev/null +++ b/src/core/trace-doc.cc @@ -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 diff --git a/src/core/trace-doc.h b/src/core/trace-doc.h new file mode 100644 index 000000000..6e2ec0600 --- /dev/null +++ b/src/core/trace-doc.h @@ -0,0 +1,50 @@ +#ifndef TRACE_DOC_H +#define TRACE_DOC_H + +#include +#include + +namespace ns3 { + +class TraceDoc +{ + typedef std::vector > 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 */ diff --git a/src/core/trace-resolver.cc b/src/core/trace-resolver.cc new file mode 100644 index 000000000..d891c94c4 --- /dev/null +++ b/src/core/trace-resolver.cc @@ -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 + */ +#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 "<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 diff --git a/src/core/trace-resolver.h b/src/core/trace-resolver.h new file mode 100644 index 000000000..3db2b42c3 --- /dev/null +++ b/src/core/trace-resolver.h @@ -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 + */ +#ifndef TRACE_RESOLVER_H +#define TRACE_RESOLVER_H + +#include +#include +#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::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 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 */ diff --git a/src/common/empty-trace-resolver.cc b/src/core/trace-source.cc similarity index 80% rename from src/common/empty-trace-resolver.cc rename to src/core/trace-source.cc index 18b9e5301..64c7d8960 100644 --- a/src/common/empty-trace-resolver.cc +++ b/src/core/trace-source.cc @@ -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 */ -#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 diff --git a/src/core/trace-source.h b/src/core/trace-source.h new file mode 100644 index 000000000..9a35a80ad --- /dev/null +++ b/src/core/trace-source.h @@ -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 + */ +#ifndef TRACE_SOURCE_H +#define TRACE_SOURCE_H + +#include + +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 */ diff --git a/src/core/uid-manager.cc b/src/core/uid-manager.cc index f6aa3f6de..364ab769c 100644 --- a/src/core/uid-manager.cc +++ b/src/core/uid-manager.cc @@ -19,8 +19,8 @@ * Author: Mathieu Lacage */ #include "uid-manager.h" -#include "ns3/fatal-error.h" -#include "ns3/assert.h" +#include "fatal-error.h" +#include "assert.h" namespace ns3 { diff --git a/src/common/uv-trace-source.h b/src/core/uv-trace-source.h similarity index 93% rename from src/common/uv-trace-source.h rename to src/core/uv-trace-source.h index b83873580..0fe84c826 100644 --- a/src/common/uv-trace-source.h +++ b/src/core/uv-trace-source.h @@ -23,11 +23,12 @@ #define UV_TRACE_SOURCE_H #include "callback-trace-source.h" +#include "trace-source.h" #include namespace ns3 { -class UVTraceSourceBase { +class UVTraceSourceBase : public TraceSource { public: typedef CallbackTraceSource 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 : \code #include - #include "ns3/uv-trace-source.h" + #include "uv-trace-source.h" ns3::UVTraceSource var; \endcode diff --git a/src/common/variable-tracer-test.cc b/src/core/variable-tracer-test.cc similarity index 98% rename from src/common/variable-tracer-test.cc rename to src/core/variable-tracer-test.cc index 29f3fc148..bd996e739 100644 --- a/src/common/variable-tracer-test.cc +++ b/src/core/variable-tracer-test.cc @@ -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 { diff --git a/src/core/wscript b/src/core/wscript index bba53ae71..455779fd6 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -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', ] diff --git a/src/devices/csma/csma-net-device.cc b/src/devices/csma/csma-net-device.cc index 531bf7314..6b5747581 100644 --- a/src/devices/csma/csma-net-device.cc +++ b/src/devices/csma/csma-net-device.cc @@ -59,6 +59,16 @@ CsmaTraceType::GetUid (void) static uint16_t uid = AllocateUid ("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) @@ -452,20 +462,23 @@ CsmaNetDevice::TransmitReadyEvent (void) } } -TraceResolver * -CsmaNetDevice::DoCreateTraceResolver (TraceContext const &context) +Ptr +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 resolver = Create (); + 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 diff --git a/src/devices/csma/csma-net-device.h b/src/devices/csma/csma-net-device.h index 62bbceab5..713611a2a 100644 --- a/src/devices/csma/csma-net-device.h +++ b/src/devices/csma/csma-net-device.h @@ -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 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 diff --git a/src/devices/point-to-point/point-to-point-net-device.cc b/src/devices/point-to-point/point-to-point-net-device.cc index a071f9246..71853b84c 100644 --- a/src/devices/point-to-point/point-to-point-net-device.cc +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -53,6 +53,11 @@ PointToPointTraceType::GetUid (void) static uint16_t uid = AllocateUid ("PointToPointTraceType"); return uid; } +std::string +PointToPointTraceType::GetTypeName (void) const +{ + return "ns3::PointToPointTraceType"; +} PointToPointNetDevice::PointToPointNetDevice (Ptr node, @@ -189,15 +194,17 @@ void PointToPointNetDevice::TransmitComplete (void) TransmitStart(p); } -TraceResolver* PointToPointNetDevice::DoCreateTraceResolver ( - TraceContext const &context) +Ptr +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 resolver = Create (); + 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; } diff --git a/src/devices/point-to-point/point-to-point-net-device.h b/src/devices/point-to-point/point-to-point-net-device.h index fa3d3b838..a5868bea4 100644 --- a/src/devices/point-to-point/point-to-point-net-device.h +++ b/src/devices/point-to-point/point-to-point-net-device.h @@ -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 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. diff --git a/src/internet-node/arp-cache.cc b/src/internet-node/arp-cache.cc index b4987daef..15a1d9316 100644 --- a/src/internet-node/arp-cache.cc +++ b/src/internet-node/arp-cache.cc @@ -19,16 +19,16 @@ * Author: Mathieu Lacage */ #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 device, Ipv4Interface *interface) +ArpCache::ArpCache (Ptr device, Ptr interface) : m_device (device), m_interface (interface), m_aliveTimeout (Seconds (120)), @@ -47,7 +47,7 @@ ArpCache::GetDevice (void) const return m_device; } -Ipv4Interface * +Ptr ArpCache::GetInterface (void) const { return m_interface; diff --git a/src/internet-node/arp-cache.h b/src/internet-node/arp-cache.h index 2cd88c85f..adf106009 100644 --- a/src/internet-node/arp-cache.h +++ b/src/internet-node/arp-cache.h @@ -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 device, Ipv4Interface *interface); + ArpCache (Ptr device, Ptr 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 GetInterface (void) const; void SetAliveTimeout (Time aliveTimeout); void SetDeadTimeout (Time deadTimeout); @@ -152,7 +152,7 @@ private: typedef sgi::hash_map::iterator CacheI; Ptr m_device; - Ipv4Interface *m_interface; + Ptr m_interface; Time m_aliveTimeout; Time m_deadTimeout; Time m_waitReplyTimeout; diff --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 17960c3f7..cd81a1058 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -40,16 +40,15 @@ ArpIpv4Interface::ArpIpv4Interface (Ptr node, Ptr device) ArpIpv4Interface::~ArpIpv4Interface () {} -TraceResolver * -ArpIpv4Interface::DoCreateTraceResolver (TraceContext const &context) +Ptr +ArpIpv4Interface::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); + Ptr resolver = Create (); if (GetDevice () != 0) { - resolver->Add ("netdevice", - MakeCallback (&NetDevice::CreateTraceResolver, PeekPointer (GetDevice ()))); + resolver->AddComposite ("netdevice", GetDevice ()); } - + resolver->SetParentResolver (Ipv4Interface::GetTraceResolver ()); return resolver; } diff --git a/src/internet-node/arp-ipv4-interface.h b/src/internet-node/arp-ipv4-interface.h index 7df522e01..c5d36a29f 100644 --- a/src/internet-node/arp-ipv4-interface.h +++ b/src/internet-node/arp-ipv4-interface.h @@ -42,9 +42,10 @@ class ArpIpv4Interface : public Ipv4Interface ArpIpv4Interface (Ptr node, Ptr device); virtual ~ArpIpv4Interface (); - private: +protected: + virtual Ptr GetTraceResolver (void) const; +private: virtual void SendTo (Packet p, Ipv4Address dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); Ptr m_node; }; diff --git a/src/internet-node/arp-l3-protocol.cc b/src/internet-node/arp-l3-protocol.cc index 100f1df88..bcc62bfe2 100644 --- a/src/internet-node/arp-l3-protocol.cc +++ b/src/internet-node/arp-l3-protocol.cc @@ -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 device) { @@ -75,7 +68,7 @@ ArpL3Protocol::FindCache (Ptr device) } } Ptr ipv4 = m_node->QueryInterface (Ipv4L3Protocol::iid); - Ipv4Interface *interface = ipv4->FindInterfaceForDevice (device); + Ptr interface = ipv4->FindInterfaceForDevice (device); ArpCache * cache = new ArpCache (device, interface); NS_ASSERT (device->IsBroadcast ()); device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache)); diff --git a/src/internet-node/arp-l3-protocol.h b/src/internet-node/arp-l3-protocol.h index a2ea8227e..5f6819df6 100644 --- a/src/internet-node/arp-l3-protocol.h +++ b/src/internet-node/arp-l3-protocol.h @@ -48,8 +48,6 @@ public: */ ArpL3Protocol (Ptr node); virtual ~ArpL3Protocol (); - - virtual TraceResolver *CreateTraceResolver (TraceContext const &context); /** * \brief Recieve a packet */ diff --git a/src/internet-node/ascii-trace.cc b/src/internet-node/ascii-trace.cc index 961edd709..6c4d11c87 100644 --- a/src/internet-node/ascii-trace.cc +++ b/src/internet-node/ascii-trace.cc @@ -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 diff --git a/src/internet-node/internet-node.cc b/src/internet-node/internet-node.cc index 5c2a3de72..5a927b55f 100644 --- a/src/internet-node/internet-node.cc +++ b/src/internet-node/internet-node.cc @@ -74,13 +74,14 @@ InternetNode::Construct (void) Object::AddInterface (ipv4L4Demux); } -void -InternetNode::DoFillTraceResolver (CompositeTraceResolver &resolver) +Ptr +InternetNode::GetTraceResolver () const { - Node::DoFillTraceResolver (resolver); + Ptr resolver = Create (); Ptr ipv4 = QueryInterface (Ipv4L3Protocol::iid); - resolver.Add ("ipv4", - MakeCallback (&Ipv4L3Protocol::CreateTraceResolver, PeekPointer (ipv4))); + resolver->AddComposite ("ipv4", ipv4); + resolver->SetParentResolver (Node::GetTraceResolver ()); + return resolver; } void diff --git a/src/internet-node/internet-node.h b/src/internet-node/internet-node.h index deabd20eb..0c855029e 100644 --- a/src/internet-node/internet-node.h +++ b/src/internet-node/internet-node.h @@ -42,8 +42,8 @@ public: protected: virtual void DoDispose(void); + virtual Ptr GetTraceResolver (void) const; private: - virtual void DoFillTraceResolver (CompositeTraceResolver &resolver); bool ReceiveFromDevice (Ptr device, const Packet &p, uint16_t protocolNumber) const; void Construct (void); }; diff --git a/src/internet-node/ipv4-interface.cc b/src/internet-node/ipv4-interface.cc index cfc398582..3ea9120d2 100644 --- a/src/internet-node/ipv4-interface.cc +++ b/src/internet-node/ipv4-interface.cc @@ -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 nd) Ipv4Interface::~Ipv4Interface () {} +void +Ipv4Interface::DoDispose (void) +{ + m_netdevice = 0; + Object::DoDispose (); +} + Ptr Ipv4Interface::GetDevice (void) const { return m_netdevice; } -TraceResolver * -Ipv4Interface::CreateTraceResolver (TraceContext const &context) -{ - return DoCreateTraceResolver (context); -} - void Ipv4Interface::SetAddress (Ipv4Address a) { diff --git a/src/internet-node/ipv4-interface.h b/src/internet-node/ipv4-interface.h index 1098c567c..1836aa3b7 100644 --- a/src/internet-node/ipv4-interface.h +++ b/src/internet-node/ipv4-interface.h @@ -26,6 +26,7 @@ #include #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 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 m_netdevice; bool m_ifup; Ipv4Address m_address; diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index be483dfa0..05200f6c2 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -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"); 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"); + static uint16_t uid = AllocateUid ("Ipv4L3ProtocolInterfaceIndex"); return uid; } +std::string +Ipv4L3ProtocolInterfaceIndex::GetTypeName (void) const +{ + return "ns3::Ipv4L3ProtocolInterfaceIndex"; +} Ipv4L3Protocol::Ipv4L3Protocol(Ptr 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 interface = Create (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 +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 *resolver = - new ArrayTraceResolver - (context, - MakeCallback (&Ipv4L3Protocol::GetNInterfaces, this), - MakeCallback (&Ipv4L3Protocol::GetInterface, this)); + Ptr resolver = Create (); + 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 device) { - Ipv4Interface *interface = new ArpIpv4Interface (m_node, device); + Ptr interface = Create (m_node, device); return AddIpv4Interface (interface); } uint32_t -Ipv4L3Protocol::AddIpv4Interface (Ipv4Interface *interface) +Ipv4L3Protocol::AddIpv4Interface (Ptrinterface) { uint32_t index = m_nInterfaces; m_interfaces.push_back (interface); m_nInterfaces++; return index; } -Ipv4Interface * +Ptr Ipv4L3Protocol::GetInterface (uint32_t index) const { uint32_t tmp = 0; @@ -296,7 +302,7 @@ Ipv4L3Protocol::GetNInterfaces (void) const return m_nInterfaces; } -Ipv4Interface * +Ptr Ipv4L3Protocol::FindInterfaceForDevice (Ptr 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 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 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 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 interface = GetInterface (i); interface->SetAddress (address); } void Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) { - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); interface->SetNetworkMask (mask); } Ipv4Mask Ipv4L3Protocol::GetNetworkMask (uint32_t i) const { - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->GetNetworkMask (); } Ipv4Address Ipv4L3Protocol::GetAddress (uint32_t i) const { - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->GetAddress (); } uint16_t Ipv4L3Protocol::GetMtu (uint32_t i) const { - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->GetMtu (); } bool Ipv4L3Protocol::IsUp (uint32_t i) const { - Ipv4Interface *interface = GetInterface (i); + Ptr interface = GetInterface (i); return interface->IsUp (); } void Ipv4L3Protocol::SetUp (uint32_t i) { - Ipv4Interface *interface = GetInterface (i); + Ptr 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 interface = GetInterface (ifaceIndex); interface->SetDown (); // Remove all routes that are going through this interface diff --git a/src/internet-node/ipv4-l3-protocol.h b/src/internet-node/ipv4-l3-protocol.h index 2cce3efa3..8eb6dbe10 100644 --- a/src/internet-node/ipv4-l3-protocol.h +++ b/src/internet-node/ipv4-l3-protocol.h @@ -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); 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 device); + Ptr FindInterfaceForDevice (Ptr device); /** * Lower layer calls this method after calling L3Demux::Lookup @@ -159,7 +170,7 @@ public: void RemoveRoute (uint32_t i); uint32_t AddInterface (Ptr device); - Ipv4Interface * GetInterface (uint32_t i) const; + Ptr GetInterface (uint32_t i) const; uint32_t GetNInterfaces (void) const; @@ -178,6 +189,7 @@ public: protected: virtual void DoDispose (void); + virtual Ptr GetTraceResolver (void) const; private: @@ -187,11 +199,10 @@ private: Ipv4Header const &ipHeader); bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device); void ForwardUp (Packet p, Ipv4Header const&ip); - uint32_t AddIpv4Interface (Ipv4Interface *interface); + uint32_t AddIpv4Interface (Ptr interface); void SetupLoopback (void); - TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const; - typedef std::list Ipv4InterfaceList; + typedef std::list > Ipv4InterfaceList; typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; Ipv4InterfaceList m_interfaces; diff --git a/src/internet-node/ipv4-l4-demux.cc b/src/internet-node/ipv4-l4-demux.cc index 977b802ba..ae4a09e42 100644 --- a/src/internet-node/ipv4-l4-demux.cc +++ b/src/internet-node/ipv4-l4-demux.cc @@ -54,6 +54,11 @@ Ipv4L4ProtocolTraceContextElement::GetUid (void) static uint16_t uid = AllocateUid ("Ipv4L4ProtocolTraceContextElement"); return uid; } +std::string +Ipv4L4ProtocolTraceContextElement::GetTypeName (void) const +{ + return "ns3::Ipv4L4ProtocolTraceContextElement"; +} Ipv4L4Demux::Ipv4L4Demux (Ptr node) @@ -78,21 +83,19 @@ Ipv4L4Demux::DoDispose (void) Object::DoDispose (); } -TraceResolver * -Ipv4L4Demux::CreateTraceResolver (TraceContext const &context) +Ptr +Ipv4L4Demux::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); + Ptr resolver = Create (); for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i) { Ptr 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 diff --git a/src/internet-node/ipv4-l4-demux.h b/src/internet-node/ipv4-l4-demux.h index 7e7fba62e..6e1208c13 100644 --- a/src/internet-node/ipv4-l4-demux.h +++ b/src/internet-node/ipv4-l4-demux.h @@ -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); 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 protocol); -private: +protected: + Ptr GetTraceResolver (void) const; virtual void DoDispose (void); +private: typedef std::list > L4List_t; L4List_t m_protocols; Ptr m_node; diff --git a/src/internet-node/ipv4-l4-protocol.h b/src/internet-node/ipv4-l4-protocol.h index f23aa510b..e54dfcc97 100644 --- a/src/internet-node/ipv4-l4-protocol.h +++ b/src/internet-node/ipv4-l4-protocol.h @@ -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 diff --git a/src/internet-node/ipv4-loopback-interface.cc b/src/internet-node/ipv4-loopback-interface.cc index be680a022..1ac8094e9 100644 --- a/src/internet-node/ipv4-loopback-interface.cc +++ b/src/internet-node/ipv4-loopback-interface.cc @@ -19,7 +19,6 @@ * Authors: * Mathieu Lacage , */ -#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) {} Ipv4LoopbackInterface::~Ipv4LoopbackInterface () {} - -TraceResolver * -Ipv4LoopbackInterface::DoCreateTraceResolver (TraceContext const &context) -{ - return new EmptyTraceResolver (context); -} - void Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest) { diff --git a/src/internet-node/ipv4-loopback-interface.h b/src/internet-node/ipv4-loopback-interface.h index 3eead3a01..8e33f81d7 100644 --- a/src/internet-node/ipv4-loopback-interface.h +++ b/src/internet-node/ipv4-loopback-interface.h @@ -43,7 +43,6 @@ class Ipv4LoopbackInterface : public Ipv4Interface private: virtual void SendTo (Packet p, Ipv4Address dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); Ptr m_node; }; diff --git a/src/internet-node/pcap-trace.cc b/src/internet-node/pcap-trace.cc index 240100fb5..3378b52c5 100644 --- a/src/internet-node/pcap-trace.cc +++ b/src/internet-node/pcap-trace.cc @@ -22,7 +22,7 @@ #include -#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); } diff --git a/src/internet-node/udp-l4-protocol.cc b/src/internet-node/udp-l4-protocol.cc index f0ef8569b..fc2a54dc9 100644 --- a/src/internet-node/udp-l4-protocol.cc +++ b/src/internet-node/udp-l4-protocol.cc @@ -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) UdpL4Protocol::~UdpL4Protocol () {} -TraceResolver * -UdpL4Protocol::CreateTraceResolver (TraceContext const &context) -{ - return new EmptyTraceResolver (context); -} - void UdpL4Protocol::DoDispose (void) { diff --git a/src/internet-node/udp-l4-protocol.h b/src/internet-node/udp-l4-protocol.h index 4d7a082d4..46fe62761 100644 --- a/src/internet-node/udp-l4-protocol.h +++ b/src/internet-node/udp-l4-protocol.h @@ -49,7 +49,6 @@ public: UdpL4Protocol (Ptr 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 diff --git a/src/mobility/hierarchical-mobility-model.cc b/src/mobility/hierarchical-mobility-model.cc index 7e4aa3fe3..046f98056 100644 --- a/src/mobility/hierarchical-mobility-model.cc +++ b/src/mobility/hierarchical-mobility-model.cc @@ -41,8 +41,8 @@ HierarchicalMobilityModel::HierarchicalMobilityModel (Ptr child, parentNotifier = Create (); 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 @@ -89,13 +89,13 @@ HierarchicalMobilityModel::DoGetSpeed (void) const } void -HierarchicalMobilityModel::ParentChanged (Ptr model) +HierarchicalMobilityModel::ParentChanged (const TraceContext &context, Ptr model) { MobilityModel::NotifyCourseChange (); } void -HierarchicalMobilityModel::ChildChanged (Ptr model) +HierarchicalMobilityModel::ChildChanged (const TraceContext &context, Ptr model) { MobilityModel::NotifyCourseChange (); } diff --git a/src/mobility/hierarchical-mobility-model.h b/src/mobility/hierarchical-mobility-model.h index 1502c516a..16be7820b 100644 --- a/src/mobility/hierarchical-mobility-model.h +++ b/src/mobility/hierarchical-mobility-model.h @@ -63,8 +63,8 @@ private: virtual void DoSet (const Position &position); virtual Speed DoGetSpeed (void) const; - void ParentChanged (Ptr model); - void ChildChanged (Ptr model); + void ParentChanged (const TraceContext &context, Ptr model); + void ChildChanged (const TraceContext &context, Ptr model); Ptr m_child; Ptr m_parent; diff --git a/src/mobility/mobility-model-notifier.cc b/src/mobility/mobility-model-notifier.cc index abb476c20..ebe64f3df 100644 --- a/src/mobility/mobility-model-notifier.cc +++ b/src/mobility/mobility-model-notifier.cc @@ -19,6 +19,8 @@ * Author: Mathieu Lacage */ #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::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 position) const { - for (std::list::const_iterator i = m_listeners.begin (); - i != m_listeners.end (); i++) - { - Listener listener = *i; - listener (position); - } + m_trace (position); +} + +Ptr +MobilityModelNotifier::GetTraceResolver (void) const +{ + Ptr resolver = + Create (); + resolver->AddSource ("course-change", + TraceDoc ("The value of the speed vector changed", + "Ptr", + "the mobility model whose course changed"), + m_trace); + resolver->SetParentResolver (Object::GetTraceResolver ()); + return resolver; } } // namespace ns3 diff --git a/src/mobility/mobility-model-notifier.h b/src/mobility/mobility-model-notifier.h index 8aec327de..1d2409f8e 100644 --- a/src/mobility/mobility-model-notifier.h +++ b/src/mobility/mobility-model-notifier.h @@ -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 > Listener; - /** * Create a new position notifier */ @@ -48,23 +47,10 @@ public: * \param position the position which just changed. */ void Notify (Ptr 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 GetTraceResolver (void) const; private: - std::list m_listeners; + CallbackTraceSource > m_trace; }; } // namespace ns3 diff --git a/src/node/net-device.cc b/src/node/net-device.cc index e3b9537aa..b47ce58a7 100644 --- a/src/node/net-device.cc +++ b/src/node/net-device.cc @@ -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 NetDevice::GetChannel (void) const { diff --git a/src/node/net-device.h b/src/node/net-device.h index cc93e6420..91f999d99 100644 --- a/src/node/net-device.h +++ b/src/node/net-device.h @@ -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. * diff --git a/src/node/node-list.cc b/src/node/node-list.cc index eb43727d9..1accfa2be 100644 --- a/src/node/node-list.cc +++ b/src/node/node-list.cc @@ -20,24 +20,12 @@ * Mathieu Lacage , */ -#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); - NodeList::Iterator Begin (void); - NodeList::Iterator End (void); - TraceResolver *CreateTraceResolver (TraceContext const &context); + NodeList::Iterator Begin (void) const; + NodeList::Iterator End (void) const; + Ptr GetTraceResolver (void) const; Ptr GetNode (uint32_t n); uint32_t GetNNodes (void); @@ -108,12 +101,12 @@ NodeListPriv::Add (Ptr 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 +NodeListPriv::GetTraceResolver (void) const { - ArrayTraceResolver, NodeListIndex> *resolver = - new ArrayTraceResolver, NodeListIndex> - (context, - MakeCallback (&NodeListPriv::GetNNodes, this), - MakeCallback (&NodeListPriv::GetNode, this)); + Ptr resolver = Create (); + resolver->AddArray ("nodes", Begin (), End (), NodeListIndex ()); return resolver; } @@ -165,17 +155,30 @@ NodeList::End (void) { return SimulationSingleton::Get ()->End (); } -TraceResolver * -NodeList::CreateTraceResolver (TraceContext const &context) -{ - return SimulationSingleton::Get ()->CreateTraceResolver (context); -} Ptr NodeList::GetNode (uint32_t n) { return SimulationSingleton::Get ()->GetNode (n); } - - +void +NodeList::Connect (std::string name, const CallbackBase &cb) +{ + SimulationSingleton::Get ()->GetTraceResolver ()->Connect (name, cb, TraceContext ()); +} +void +NodeList::Disconnect (std::string name, const CallbackBase &cb) +{ + SimulationSingleton::Get ()->GetTraceResolver ()->Disconnect (name, cb); +} +void +NodeList::TraceAll (std::ostream &os) +{ + SimulationSingleton::Get ()->GetTraceResolver ()->TraceAll (os, TraceContext ()); +} +Ptr +NodeList::GetTraceResolver (void) +{ + return SimulationSingleton::Get ()->GetTraceResolver (); +} }//namespace ns3 diff --git a/src/node/node-list.h b/src/node/node-list.h index 1fdcd9e0e..dc0e69d8c 100644 --- a/src/node/node-list.h +++ b/src/node/node-list.h @@ -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 >::iterator Iterator; + typedef std::vector< Ptr >::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 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 GetTraceResolver (void); +private: }; }//namespace ns3 diff --git a/src/node/node.cc b/src/node/node.cc index ee83e8588..171af4e2d 100644 --- a/src/node/node.cc +++ b/src/node/node.cc @@ -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"); 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 +Node::GetTraceResolver (void) const { - CompositeTraceResolver *resolver = new CompositeTraceResolver (context); - DoFillTraceResolver (*resolver); + Ptr resolver = Create (); + 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,NodeNetDeviceIndex> *resolver = - new ArrayTraceResolver,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() { diff --git a/src/node/node.h b/src/node/node.h index f4d898f53..cd032e2e0 100644 --- a/src/node/node.h +++ b/src/node/node.h @@ -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 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 device, const Packet &packet, uint16_t protocol, const Address &from); void Construct (void); - TraceResolver *CreateDevicesTraceResolver (const TraceContext &context); struct ProtocolHandlerEntry { ProtocolHandler handler; diff --git a/src/node/queue.cc b/src/node/queue.cc index 72eafed69..8ed033b66 100644 --- a/src/node/queue.cc +++ b/src/node/queue.cc @@ -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 +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 resolver = Create (); + 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; } diff --git a/src/node/queue.h b/src/node/queue.h index d135fff68..b8531c9c7 100644 --- a/src/node/queue.h +++ b/src/node/queue.h @@ -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 GetTraceResolver (void) const; // called by subclasses to notify parent of packet drops. void Drop (const Packet& p); diff --git a/src/routing/global-routing/global-route-manager-impl.cc b/src/routing/global-routing/global-route-manager-impl.cc index c2b7021c9..10f07ca85 100644 --- a/src/routing/global-routing/global-route-manager-impl.cc +++ b/src/routing/global-routing/global-route-manager-impl.cc @@ -1407,27 +1407,6 @@ GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v) namespace ns3 { -class GlobalRouterTestNode : public Node -{ -public: - GlobalRouterTestNode (); - -private: - virtual void DoAddDevice (Ptr device) const {}; - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); -}; - -GlobalRouterTestNode::GlobalRouterTestNode () -{ -// Ptr ipv4 = Create (this); -} - - TraceResolver* -GlobalRouterTestNode::DoCreateTraceResolver (TraceContext const &context) -{ - return 0; -} - class GlobalRouteManagerImplTest : public Test { public: GlobalRouteManagerImplTest (); diff --git a/utils/print-trace-sources.cc b/utils/print-trace-sources.cc new file mode 100644 index 000000000..af7cfb755 --- /dev/null +++ b/utils/print-trace-sources.cc @@ -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 = Create (); + node->AddInterface (Create ()); + + Ptr p2p = Create (node); + p2p->AddQueue (Queue::CreateDefault ()); + Ptr csma = Create (node); + csma->AddQueue (Queue::CreateDefault ()); + + TraceResolver::SourceCollection collection; + NodeList::GetTraceResolver ()->CollectSources ("", TraceContext (), &collection); + PrintDoxygenText (&collection, std::cout); + + return 0; +} diff --git a/utils/wscript b/utils/wscript index 464d974f1..15fbfa512 100644 --- a/utils/wscript +++ b/utils/wscript @@ -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'