tracers+docs: Correcting compilation and installation of trace helpers

Also in this commit an example on how to use trace helpers, including
how to build graphs using R.
diff --git a/utils/tracers/ndn-l3-aggregate-tracer.cc b/utils/tracers/ndn-l3-aggregate-tracer.cc
index 1280ede..35b85ec 100644
--- a/utils/tracers/ndn-l3-aggregate-tracer.cc
+++ b/utils/tracers/ndn-l3-aggregate-tracer.cc
@@ -28,18 +28,63 @@
 #include "ns3/ndn-face.h"
 #include "ns3/ndn-interest.h"
 #include "ns3/ndn-content-object.h"
+#include "ns3/simulator.h"
+#include "ns3/node-list.h"
+#include "ns3/log.h"
+
+#include <fstream>
+
+NS_LOG_COMPONENT_DEFINE ("ndn.L3AggregateTracer");
 
 namespace ns3 {
 namespace ndn {
 
-L3AggregateTracer::L3AggregateTracer (Ptr<Node> node)
-: L3Tracer (node)
+boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3AggregateTracer> > >
+L3AggregateTracer::InstallAll (const std::string &file, Time averagingPeriod/* = Seconds (0.5)*/)
+{
+  using namespace boost;
+  using namespace std;
+  
+  std::list<Ptr<L3AggregateTracer> > tracers;
+  boost::shared_ptr<std::ofstream> outputStream (new std::ofstream ());
+  outputStream->open (file.c_str (), std::ios_base::out | std::ios_base::trunc);
+
+  if (!outputStream->is_open ())
+    return boost::make_tuple (outputStream, tracers);
+
+  for (NodeList::Iterator node = NodeList::Begin ();
+       node != NodeList::End ();
+       node++)
+    {
+      NS_LOG_DEBUG ("Node: " << (*node)->GetId ());
+
+      Ptr<L3AggregateTracer> trace = Create<L3AggregateTracer> (outputStream, *node);
+      trace->SetAveragingPeriod (averagingPeriod);
+      tracers.push_back (trace);
+    }
+
+  if (tracers.size () > 0)
+    {
+      // *m_l3RateTrace << "# "; // not necessary for R's read.table
+      tracers.front ()->PrintHeader (*outputStream);
+      *outputStream << "\n";
+    }
+
+  return boost::make_tuple (outputStream, tracers);
+}
+
+
+
+L3AggregateTracer::L3AggregateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node)
+  : L3Tracer (node)
+  , m_os (os)
 {
   Reset ();
 }
 
-L3AggregateTracer::L3AggregateTracer (const std::string &node)
-: L3Tracer (node)
+L3AggregateTracer::L3AggregateTracer (boost::shared_ptr<std::ostream> os, const std::string &node)
+  : L3Tracer (node)
+  , m_os (os)
 {
   Reset ();
 }
@@ -49,144 +94,157 @@
 };
 
 void
-L3AggregateTracer::Reset ()
+L3AggregateTracer::SetAveragingPeriod (const Time &period)
 {
-  m_packets.Reset ();
-  m_bytes.Reset ();
+  m_period = period;
+  m_printEvent.Cancel ();
+  m_printEvent = Simulator::Schedule (m_period, &L3AggregateTracer::PeriodicPrinter, this);
 }
 
+void
+L3AggregateTracer::PeriodicPrinter ()
+{
+  Print (*m_os);
+  Reset ();
+  
+  m_printEvent = Simulator::Schedule (m_period, &L3AggregateTracer::PeriodicPrinter, this);
+}
 
 void
 L3AggregateTracer::PrintHeader (std::ostream &os) const
 {
-  os << "Node" << "\t"
-     << "InInterests" << "\t"
-     << "OutInterests" << "\t"
-     << "DropInterests" << "\t"
-    
-     << "InNacks" << "\t"
-     << "OutNacks" << "\t"
-     << "DropNacks" << "\t"
-    
-     << "InData" << "\t"
-     << "OutData" << "\t"
-     << "DropData" << "\t"
-    
-     << "InInterestsBytes" << "\t"
-     << "OutInterestsBytes" << "\t"
-     << "DropInterestsBytes" << "\t"
-    
-     << "InNacksBytes" << "\t"
-     << "OutNacksBytes" << "\t"
-     << "DropNacksBytes" << "\t"
-    
-     << "InDataBytes" << "\t"
-     << "OutDataBytes" << "\t"
-     << "DropDataBytes";
+  os << "Time" << "\t"
+
+     << "Node" << "\t"
+     << "FaceId" << "\t"
+     << "FaceDescr" << "\t"
+
+     << "Type" << "\t"
+     << "Packets" << "\t"
+     << "Kilobytes";
 }
 
 void
+L3AggregateTracer::Reset ()
+{
+  for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats> >::iterator stats = m_stats.begin ();
+       stats != m_stats.end ();
+       stats++)
+    {
+      stats->second.get<0> ().Reset ();
+      stats->second.get<1> ().Reset ();
+    }
+}
+
+
+#define STATS(INDEX) stats->second.get<INDEX> ()
+
+#define PRINTER(printName, fieldName) \
+  os << time.ToDouble (Time::S) << "\t"                                 \
+  << m_node << "\t"                                                     \
+  << stats->first->GetId () << "\t"                                     \
+  << *stats->first << "\t"                                              \
+  << printName << "\t"                                                  \
+  << STATS(0).fieldName << "\t"                                         \
+  << STATS(1).fieldName / 1024.0 << "\n";
+
+
+void
 L3AggregateTracer::Print (std::ostream &os) const
 {
-  os << m_node << "\t"
-     << m_packets.m_inInterests   << "\t"
-     << m_packets.m_outInterests  << "\t"
-     << m_packets.m_dropInterests << "\t"
+  for (std::map<Ptr<const Face>, boost::tuple<Stats, Stats> >::iterator stats = m_stats.begin ();
+       stats != m_stats.end ();
+       stats++)
+    {
+      Time time = Simulator::Now ();
 
-     << m_packets.m_inNacks   << "\t"
-     << m_packets.m_outNacks  << "\t"
-     << m_packets.m_dropNacks << "\t"
+      PRINTER ("InInterests",   m_inInterests);
+      PRINTER ("OutInterests",  m_outInterests);
+      // PRINTER ("DropInterests", m_dropInterests);
+      
+      PRINTER ("InNacks",   m_inNacks);
+      PRINTER ("OutNacks",  m_outNacks);
+      // PRINTER ("DropNacks", m_dropNacks);
 
-     << m_packets.m_inData   << "\t"
-     << m_packets.m_outData  << "\t"
-     << m_packets.m_dropData << "\t"
-
-     << m_bytes.m_inInterests   << "\t"
-     << m_bytes.m_outInterests  << "\t"
-     << m_bytes.m_dropInterests << "\t"
-
-     << m_bytes.m_inNacks   << "\t"
-     << m_bytes.m_outNacks  << "\t"
-     << m_bytes.m_dropNacks << "\t"
-
-     << m_bytes.m_inData   << "\t"
-     << m_bytes.m_outData  << "\t"
-     << m_bytes.m_dropData;
+      PRINTER ("InData",   m_inData);
+      PRINTER ("OutData",  m_outData);
+      // PRINTER ("DropData", m_dropData);
+    }
 }
 
 void
 L3AggregateTracer::OutInterests  (std::string context,
-                                  Ptr<const InterestHeader> header, Ptr<const Face>)
+                                  Ptr<const InterestHeader> header, Ptr<const Face> face)
 {
-  m_packets.m_outInterests++;
-  m_bytes.m_outInterests += header->GetSerializedSize ();
+  m_stats[face].get<0> ().m_outInterests ++;
+  m_stats[face].get<1> ().m_outInterests += header->GetSerializedSize ();
 }
 
 void
 L3AggregateTracer::InInterests   (std::string context,
-                                  Ptr<const InterestHeader> header, Ptr<const Face>)
+                                  Ptr<const InterestHeader> header, Ptr<const Face> face)
 {
-  m_packets.m_inInterests++;
-  m_bytes.m_inInterests += header->GetSerializedSize ();
+  m_stats[face].get<0> ().m_inInterests ++;
+  m_stats[face].get<1> ().m_inInterests += header->GetSerializedSize ();
 }
 
 void
 L3AggregateTracer::DropInterests (std::string context,
-                                  Ptr<const InterestHeader> header, Ptr<const Face>)
+                                  Ptr<const InterestHeader> header, Ptr<const Face> face)
 {
-  m_packets.m_dropInterests++;
-  m_bytes.m_dropInterests += header->GetSerializedSize ();
+  m_stats[face].get<0> ().m_dropInterests ++;
+  m_stats[face].get<1> ().m_dropInterests += header->GetSerializedSize ();
 }
 
 void
 L3AggregateTracer::OutNacks  (std::string context,
-                              Ptr<const InterestHeader> header, Ptr<const Face>)
+                              Ptr<const InterestHeader> header, Ptr<const Face> face)
 {
-  m_packets.m_outNacks++;
-  m_bytes.m_outNacks += header->GetSerializedSize ();
+  m_stats[face].get<0> ().m_outNacks ++;
+  m_stats[face].get<1> ().m_outNacks += header->GetSerializedSize ();
 }
 
 void
 L3AggregateTracer::InNacks   (std::string context,
-                              Ptr<const InterestHeader> header, Ptr<const Face>)
+                              Ptr<const InterestHeader> header, Ptr<const Face> face)
 {
-  m_packets.m_inNacks++;
-  m_bytes.m_inNacks += header->GetSerializedSize ();
+  m_stats[face].get<0> ().m_inNacks ++;
+  m_stats[face].get<1> ().m_inNacks += header->GetSerializedSize ();
 }
 
 void
 L3AggregateTracer::DropNacks (std::string context,
-                              Ptr<const InterestHeader> header, Ptr<const Face>)
+                              Ptr<const InterestHeader> header, Ptr<const Face> face)
 {
-  m_packets.m_dropNacks++;
-  m_bytes.m_dropNacks += header->GetSerializedSize ();
+  m_stats[face].get<0> ().m_dropNacks ++;
+  m_stats[face].get<1> ().m_dropNacks += header->GetSerializedSize ();
 }
 
 void
 L3AggregateTracer::OutData  (std::string context,
                              Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
-                             bool fromCache, Ptr<const Face>)
+                             bool fromCache, Ptr<const Face> face)
 {
-  m_packets.m_outData++;
-  m_bytes.m_outData += header->GetSerializedSize () + payload->GetSize ();
+  m_stats[face].get<0> ().m_outData ++;
+  m_stats[face].get<1> ().m_outData += header->GetSerializedSize () + payload->GetSize ();
 }
 
 void
 L3AggregateTracer::InData   (std::string context,
                              Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
-                             Ptr<const Face>)
+                             Ptr<const Face> face)
 {
-  m_packets.m_inData++;
-  m_bytes.m_inData += header->GetSerializedSize () + payload->GetSize ();
+  m_stats[face].get<0> ().m_inData ++;
+  m_stats[face].get<1> ().m_inData += header->GetSerializedSize () + payload->GetSize ();
 }
 
 void
 L3AggregateTracer::DropData (std::string context,
                              Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
-                             Ptr<const Face>)
+                             Ptr<const Face> face)
 {
-  m_packets.m_dropData++;
-  m_bytes.m_dropData += header->GetSerializedSize () + payload->GetSize ();
+  m_stats[face].get<0> ().m_dropData ++;
+  m_stats[face].get<1> ().m_dropData += header->GetSerializedSize () + payload->GetSize ();
 }
 
 } // namespace ndn
diff --git a/utils/tracers/ndn-l3-aggregate-tracer.h b/utils/tracers/ndn-l3-aggregate-tracer.h
index bd9cbd0..a04df67 100644
--- a/utils/tracers/ndn-l3-aggregate-tracer.h
+++ b/utils/tracers/ndn-l3-aggregate-tracer.h
@@ -26,16 +26,55 @@
 #include <ns3/nstime.h>
 #include <ns3/event-id.h>
 
+#include <boost/tuple/tuple.hpp>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <list>
+
 namespace ns3 {
 namespace ndn {
 
+/**
+ * @ingroup ndn
+ * @brief CCNx network-layer tracer for aggregate packet counts
+ */
 class L3AggregateTracer : public L3Tracer
 {
 public:
-  L3AggregateTracer (Ptr<Node> node);
-  L3AggregateTracer (const std::string &node);
-  virtual ~L3AggregateTracer ();
+  /**
+   * @brief Trace constructor that attaches to the node using node pointer
+   * @param os    reference to the output stream
+   * @param node  pointer to the node
+   */
+  L3AggregateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node);
   
+  /**
+   * @brief Trace constructor that attaches to the node using node name
+   * @param os        reference to the output stream
+   * @param nodeName  name of the node registered using Names::Add
+   */
+  L3AggregateTracer (boost::shared_ptr<std::ostream> os, const std::string &nodeName);
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~L3AggregateTracer ();
+
+  /**
+   * @brief Helper method to install tracers on all simulation nodes
+   *
+   * @param file File to which traces will be written
+   * @param averagingPeriod How often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   * 
+   */
+  static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3AggregateTracer> > >
+  InstallAll (const std::string &file, Time averagingPeriod = Seconds (0.5));
+
+protected: 
+  // from L3Tracer
   virtual void
   PrintHeader (std::ostream &os) const;
 
@@ -80,17 +119,21 @@
 
 protected:
   void
+  SetAveragingPeriod (const Time &period);
+
+  void
   Reset ();
 
   void
   PeriodicPrinter ();
   
 protected:
-  Stats m_packets;
-  Stats m_bytes;
+  boost::shared_ptr<std::ostream> m_os;
 
   Time m_period;
   EventId m_printEvent;
+  
+  mutable std::map<Ptr<const Face>, boost::tuple<Stats, Stats> > m_stats;
 };
 
 } // namespace ndn
diff --git a/utils/tracers/ndn-l3-rate-tracer.cc b/utils/tracers/ndn-l3-rate-tracer.cc
index 6604f0b..f588503 100644
--- a/utils/tracers/ndn-l3-rate-tracer.cc
+++ b/utils/tracers/ndn-l3-rate-tracer.cc
@@ -157,7 +157,7 @@
   << STATS(2).fieldName << "\t"                                         \
   << STATS(3).fieldName << "\t"                                         \
   << STATS(0).fieldName << "\t"                                         \
-  << STATS(1).fieldName << "\n";
+  << STATS(1).fieldName / 1024.0 << "\n";
 
 void
 L3RateTracer::Print (std::ostream &os) const
@@ -236,8 +236,8 @@
                         Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
                         bool fromCache, Ptr<const Face> face)
 {
-  m_stats[face].get<0> ().m_inData ++;
-  m_stats[face].get<1> ().m_inData += header->GetSerializedSize () + payload->GetSize ();
+  m_stats[face].get<0> ().m_outData ++;
+  m_stats[face].get<1> ().m_outData += header->GetSerializedSize () + payload->GetSize ();
 }
 
 void
@@ -245,8 +245,8 @@
                         Ptr<const ContentObjectHeader> header, Ptr<const Packet> payload,
                         Ptr<const Face> face)
 {
-  m_stats[face].get<0> ().m_outData ++;
-  m_stats[face].get<1> ().m_outData += header->GetSerializedSize () + payload->GetSize ();
+  m_stats[face].get<0> ().m_inData ++;
+  m_stats[face].get<1> ().m_inData += header->GetSerializedSize () + payload->GetSize ();
 }
 
 void
diff --git a/utils/tracers/ndn-l3-rate-tracer.h b/utils/tracers/ndn-l3-rate-tracer.h
index ced3113..791d953 100644
--- a/utils/tracers/ndn-l3-rate-tracer.h
+++ b/utils/tracers/ndn-l3-rate-tracer.h
@@ -35,31 +35,54 @@
 namespace ndn {
 
 /**
- * @ingroup ccnx
+ * @ingroup ndn
  * @brief CCNx network-layer rate tracer
  */
 class L3RateTracer : public L3Tracer
 {
 public:
   /**
-   * @brief Network layer tracer constructor
+   * @brief Trace constructor that attaches to the node using node pointer
+   * @param os    reference to the output stream
+   * @param node  pointer to the node
    */
   L3RateTracer (boost::shared_ptr<std::ostream> os, Ptr<Node> node);
+
+  /**
+   * @brief Trace constructor that attaches to the node using node name
+   * @param os        reference to the output stream
+   * @param nodeName  name of the node registered using Names::Add
+   */
   L3RateTracer (boost::shared_ptr<std::ostream> os, const std::string &node);
+
+  /**
+   * @brief Destructor
+   */
   virtual ~L3RateTracer ();
 
+  /**
+   * @brief Helper method to install tracers on all simulation nodes
+   *
+   * @param file File to which traces will be written
+   * @param averagingPeriod Defines averaging period for the rate calculation,
+   *        as well as how often data will be written into the trace file (default, every half second)
+   *
+   * @returns a tuple of reference to output stream and list of tracers. !!! Attention !!! This tuple needs to be preserved
+   *          for the lifetime of simulation, otherwise SEGFAULTs are inevitable
+   * 
+   */
   static boost::tuple< boost::shared_ptr<std::ostream>, std::list<Ptr<L3RateTracer> > >
   InstallAll (const std::string &file, Time averagingPeriod = Seconds (0.5));
-  
-  void
-  SetAveragingPeriod (const Time &period);
-  
+
+  // from L3Tracer
   virtual void
   PrintHeader (std::ostream &os) const;
 
   virtual void
   Print (std::ostream &os) const;
 
+protected:
+  // from L3Tracer
   virtual void
   OutInterests  (std::string context,
                  Ptr<const InterestHeader>, Ptr<const Face>);
@@ -98,6 +121,9 @@
 
 private:
   void
+  SetAveragingPeriod (const Time &period);
+
+  void
   PeriodicPrinter ();
   
   void
diff --git a/utils/tracers/ndn-l3-tracer.h b/utils/tracers/ndn-l3-tracer.h
index 74c0ef9..72c4cac 100644
--- a/utils/tracers/ndn-l3-tracer.h
+++ b/utils/tracers/ndn-l3-tracer.h
@@ -38,19 +38,43 @@
 class L3Tracer : public SimpleRefCount<L3Tracer>
 {
 public:
+  /**
+   * @brief Trace constructor that attaches to the node using node pointer
+   * @param node  pointer to the node
+   */
   L3Tracer (Ptr<Node> node);
+
+  /**
+   * @brief Trace constructor that attaches to the node using node name
+   * @param nodeName  name of the node registered using Names::Add
+   */
   L3Tracer (const std::string &node);
+
+  /**
+   * @brief Destructor
+   */
   virtual ~L3Tracer ();
 
-  void
-  Connect ();
-  
+  /**
+   * @brief Print head of the trace (e.g., for post-processing)
+   *
+   * @param os reference to output stream
+   */
   virtual void
   PrintHeader (std::ostream &os) const = 0;
 
+  /**
+   * @brief Print current trace data
+   *
+   * @param os reference to output stream
+   */
   virtual void
   Print (std::ostream &os) const = 0;
   
+protected:
+  void
+  Connect ();
+  
   virtual void
   OutInterests  (std::string context,
                  Ptr<const InterestHeader>, Ptr<const Face>) = 0;
@@ -119,6 +143,9 @@
   };
 };
 
+/**
+ * @brief Helper to dump the trace to an output stream
+ */
 inline std::ostream&
 operator << (std::ostream &os, const L3Tracer &tracer)
 {