Stats tree seems to work properly, including pruning of "empty" leaves
diff --git a/utils/load-stats-face.cc b/utils/load-stats-face.cc
index 834004a..2e66197 100644
--- a/utils/load-stats-face.cc
+++ b/utils/load-stats-face.cc
@@ -58,6 +58,12 @@
   return *this;
 }
 
+bool
+LoadStatsFace::IsZero () const
+{
+  return m_count.IsZero () && m_satisfied.IsZero () && m_unsatisfied.IsZero ();
+}
+
 std::ostream &
 operator << (std::ostream &os, const LoadStatsFace &stats)
 {
diff --git a/utils/load-stats-face.h b/utils/load-stats-face.h
index ad033b4..6c85a68 100644
--- a/utils/load-stats-face.h
+++ b/utils/load-stats-face.h
@@ -59,6 +59,9 @@
 
   LoadStatsFace &
   operator += (const LoadStatsFace &load);
+
+  bool
+  IsZero () const;
   
 private:
   LoadStats m_count;
diff --git a/utils/load-stats-node.cc b/utils/load-stats-node.cc
index 34875c5..59184c8 100644
--- a/utils/load-stats-node.cc
+++ b/utils/load-stats-node.cc
@@ -20,15 +20,24 @@
 
 #include "load-stats-node.h"
 #include "ns3/ccnx-face.h"
+#include "ns3/log.h"
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+
+namespace ll = boost::lambda;
 
 using namespace ns3;
 
+NS_LOG_COMPONENT_DEFINE ("LoadStatsNode");
+
 namespace ndnSIM
 {
 
 void
 LoadStatsNode::Step ()
 {
+  NS_LOG_FUNCTION (this);
+  
   m_pit.Step ();
   
   for (stats_container::iterator item = m_incoming.begin ();
@@ -107,6 +116,8 @@
 LoadStatsNode &
 LoadStatsNode::operator += (const LoadStatsNode &stats)
 {
+  NS_LOG_FUNCTION (this << &stats);
+  
   m_pit += stats.m_pit;
   
   // aggregate incoming
@@ -128,10 +139,37 @@
   return *this;
 }
 
+bool
+LoadStatsNode::IsZero () const
+{
+  bool zero = true;
+  std::for_each (m_incoming.begin (), m_incoming.end (),
+                 zero &= ll::bind (&LoadStatsFace::IsZero,
+                                   ll::bind (&stats_container::value_type::second, ll::_1)));
+
+  std::for_each (m_outgoing.begin (), m_outgoing.end (),
+                 zero &= ll::bind (&LoadStatsFace::IsZero,
+                                   ll::bind (&stats_container::value_type::second, ll::_1)));
+  zero &= m_pit.IsZero ();
+  
+  return zero;  
+}
+
+bool
+LoadStatsNode::operator == (const LoadStatsNode &other) const
+{
+  if (other.m_incoming.size () > 0 ||
+      other.m_outgoing.size () > 0 ||
+      !other.m_pit.IsZero ())
+    return false;
+
+  return IsZero ();
+}
+
 std::ostream&
 operator << (std::ostream &os, const LoadStatsNode &node)
 {
-  os << "PIT: " << node.m_pit << std::endl;
+  os << "PIT: " << node.m_pit;// << std::endl;
   return os;
 }
 
diff --git a/utils/load-stats-node.h b/utils/load-stats-node.h
index 5376144..e91b094 100644
--- a/utils/load-stats-node.h
+++ b/utils/load-stats-node.h
@@ -89,15 +89,15 @@
   pit () const;
 
   bool
-  operator == (const LoadStatsNode &other) const
-  {
-    return false;
-  }
-
+  IsZero () const;
+  
+  bool
+  operator == (const LoadStatsNode &other) const;
+  
   bool
   operator != (const LoadStatsNode &other) const
   {
-    return true;
+    return !(*this == other);
   }
 
   LoadStatsNode &
diff --git a/utils/load-stats.cc b/utils/load-stats.cc
index ee61df4..8a663e3 100644
--- a/utils/load-stats.cc
+++ b/utils/load-stats.cc
@@ -19,6 +19,7 @@
  */
 
 #include "load-stats.h"
+#include "ns3/log.h"
 
 using namespace ns3;
 
@@ -28,6 +29,8 @@
 
 const double EPSILON = 0.000001;
 
+NS_LOG_COMPONENT_DEFINE ("LoadStats");
+
 namespace ndnSIM
 {
 
@@ -42,6 +45,8 @@
 void
 LoadStats::Step ()
 {
+  // NS_LOG_FUNCTION (this);
+
   // do magic
   avg1_  = EXP_1 * avg1_  + (1 - EXP_1)  * counter_;
   avg5_  = EXP_1 * avg5_  + (1 - EXP_5)  * counter_;
@@ -53,25 +58,17 @@
 LoadStats &
 LoadStats::operator ++ (int)
 {
+  // NS_LOG_FUNCTION (this);
+
   counter_ ++;
   return *this;
 }
 
-// void
-// LoadStats::Increment (uint32_t amount)
-// {
-//   counter_ += amount;
-// }
-
-// uint32_t
-// LoadStats::GetCounter () const
-// {
-//   return counter_;
-// }
-
 LoadStats &
 LoadStats::operator += (const LoadStats &stats)
 {
+  // NS_LOG_FUNCTION (this << &stats << stats.counter_);
+
   counter_ += stats.counter_;
   return *this;
 }
@@ -83,9 +80,10 @@
 }
 
 bool
-LoadStats::IsEmpty () const
+LoadStats::IsZero () const
 {
-  return (avg1_ < EPSILON &&
+  return (counter_ == 0 &&
+          avg1_ < EPSILON &&
 	  avg5_ < EPSILON &&
 	  avg15_ < EPSILON);
 }
@@ -93,8 +91,7 @@
 std::ostream &
 operator << (std::ostream &os, const LoadStats &stats)
 {
-  LoadStats::stats_tuple data = stats.GetStats ();
-  os << data.get<0> () << ", " << data.get<1> () << ", " << data.get<2> ();// << std::endl;
+  os << stats.avg1_ << ", " << stats.avg5_ << ", " << stats.avg15_;
   return os;
 }
 
diff --git a/utils/load-stats.h b/utils/load-stats.h
index 8b2433e..a9f2e5f 100644
--- a/utils/load-stats.h
+++ b/utils/load-stats.h
@@ -53,7 +53,7 @@
   GetStats () const;
 
   bool
-  IsEmpty () const;
+  IsZero () const;
   
 private:
   uint32_t counter_;
@@ -61,6 +61,9 @@
   double avg1_;
   double avg5_;
   double avg15_;
+
+  friend std::ostream &
+  operator << (std::ostream &os, const LoadStats &stats);
 };
 
 std::ostream &
diff --git a/utils/stats-tree.cc b/utils/stats-tree.cc
index eb37c02..6d2ff28 100644
--- a/utils/stats-tree.cc
+++ b/utils/stats-tree.cc
@@ -37,27 +37,28 @@
 void
 StatsTree::Step ()
 {
+  NS_LOG_FUNCTION (this);
+
   // walking the tree, aggregating and stepping on every node, starting the leaves
   // for (trie_type::
 
   WalkLeftRightRoot (&m_tree);
+  m_tree.payload ().Step ();
+  NS_LOG_DEBUG ("[" << m_tree.key () << "] " << m_tree.payload ());  
 }
 
 void
 StatsTree::NewPitEntry (const ns3::CcnxNameComponents &key)
 {
   std::pair<tree_type::iterator, bool> item = m_tree.insert (key, LoadStatsNode ());
-  NS_ASSERT (item.second == false); // should always return false
 
   item.first->payload ().NewPitEntry ();
-  NS_LOG_DEBUG ("NewPitEntry: " << item.first->payload ());
 }
 
 void
 StatsTree::Incoming (const CcnxNameComponents &key, Ptr<CcnxFace> face)
 {
   std::pair<tree_type::iterator, bool> item = m_tree.insert (key, LoadStatsNode ());
-  NS_ASSERT (item.second == false); // should always return false
 
   item.first->payload ().AddIncoming (face);
 }
@@ -66,7 +67,6 @@
 StatsTree::Outgoing (const CcnxNameComponents &key, Ptr<CcnxFace> face)
 {
   std::pair<tree_type::iterator, bool> item = m_tree.insert (key, LoadStatsNode ());
-  NS_ASSERT (item.second == false); // should always return false
 
   item.first->payload ().AddOutgoing (face);
 }
@@ -75,7 +75,6 @@
 StatsTree::Satisfy (const CcnxNameComponents &key)
 {
   std::pair<tree_type::iterator, bool> item = m_tree.insert (key, LoadStatsNode ());
-  NS_ASSERT (item.second == false); // should always return false
 
   item.first->payload ().Satisfy ();
 }
@@ -84,42 +83,49 @@
 StatsTree::Timeout (const CcnxNameComponents &key)
 {
   std::pair<tree_type::iterator, bool> item = m_tree.insert (key, LoadStatsNode ());
-  NS_ASSERT (item.second == false); // should always return false
 
   item.first->payload ().Timeout ();
 }
 
+// const LoadStatsNode &
+// StatsTree::Get (const ns3::CcnxNameComponents &key) const
 const LoadStatsNode &
-StatsTree::Get (const ns3::CcnxNameComponents &key) const
+StatsTree::operator [] (const ns3::CcnxNameComponents &key) const
 {
   tree_type::iterator foundItem, lastItem;
   bool reachLast;
   boost::tie (foundItem, reachLast, lastItem) = const_cast<tree_type&> (m_tree).find (key);
 
-  NS_ASSERT_MSG (foundItem == lastItem, "Found item should always be the same as last item (same address)");
-
-  return foundItem->payload ();
+  return lastItem->payload ();
 }
 
 const LoadStatsNode&
 StatsTree::WalkLeftRightRoot (tree_type *node)
 {
   tree_type::point_iterator item (*node), end;
-  
-  for (; item != end; item++)
+
+  while (item != end)
     {
       node->payload () += WalkLeftRightRoot (&*item);
-      NS_LOG_DEBUG (node << ", " << node->payload ());
-    }
+      item->payload ().Step ();
 
-  node->payload ().Step ();
+      NS_LOG_DEBUG ("[" << item->key () << "] " << item->payload ());
+      // item->prune (); // will do only if necessary
+
+      tree_type::point_iterator prune_iterator = item;
+      item++;
+
+      prune_iterator->prune ();
+    }
+  
   return node->payload ();
 }
 
 std::ostream &
 operator << (std::ostream &os, const StatsTree &tree)
 {
-  os << tree.m_tree.payload ();
+  // os << "[" << tree.m_tree.key () << "]: " << tree.m_tree.payload ();
+  os << tree.m_tree;
   return os;
 }
 
diff --git a/utils/stats-tree.h b/utils/stats-tree.h
index e731d32..1f9d146 100644
--- a/utils/stats-tree.h
+++ b/utils/stats-tree.h
@@ -55,8 +55,10 @@
   void
   Timeout (const ns3::CcnxNameComponents &key);
 
+  // const LoadStatsNode &
+  // Get (const ns3::CcnxNameComponents &key) const;
   const LoadStatsNode &
-  Get (const ns3::CcnxNameComponents &key) const;
+  operator [] (const ns3::CcnxNameComponents &key) const;
   
 private:
   const LoadStatsNode &
diff --git a/utils/trie.h b/utils/trie.h
index 51a7678..dbd3e1d 100644
--- a/utils/trie.h
+++ b/utils/trie.h
@@ -377,6 +377,11 @@
   {
     payload_ = payload;
   }
+
+  Key key () const
+  {
+    return key_;
+  }
   
   inline void
   PrintStat (std::ostream &os) const;