Disabling FIB-entry-limit decrease. Implementing probabilistic interest
acceptance based on accumulated statistics.

Statistics generation is changed to real 1-second averaging
diff --git a/model/fw/fw-stats.cc b/model/fw/fw-stats.cc
index 959d25f..46cd775 100644
--- a/model/fw/fw-stats.cc
+++ b/model/fw/fw-stats.cc
@@ -177,6 +177,22 @@
 }
 
 void
+FwStats::DidExhaustForwardingOptions (const Ptr<Face> &incomingFace,
+                                      Ptr<InterestHeader> header,
+                                      const Ptr<const Packet> &packet,
+                                      Ptr<pit::Entry> pitEntry)
+{
+  super::DidExhaustForwardingOptions (incomingFace, header, packet, pitEntry);
+  
+  if (pitEntry->GetOutgoing ().size () == 0)
+    {
+      m_stats.Timeout (pitEntry->GetPrefix ().cut (1));
+  
+      ScheduleRefreshingIfNecessary ();
+    }
+}
+
+void
 FwStats::ScheduleRefreshingIfNecessary ()
 {
   if (m_statsRefreshEvent.IsRunning ()) return;
diff --git a/model/fw/fw-stats.h b/model/fw/fw-stats.h
index 1a516d8..404f487 100644
--- a/model/fw/fw-stats.h
+++ b/model/fw/fw-stats.h
@@ -96,6 +96,12 @@
   virtual void
   WillEraseTimedOutPendingInterest (Ptr<pit::Entry> pitEntry);
 
+  virtual void
+  DidExhaustForwardingOptions (const Ptr<Face> &incomingFace,
+                               Ptr<InterestHeader> header,
+                               const Ptr<const Packet> &packet,
+                               Ptr<pit::Entry> pitEntry);
+  
   // from Object
   void
   DoDispose ();
diff --git a/model/fw/per-fib-limits.cc b/model/fw/per-fib-limits.cc
index ba11f7f..08ef66b 100644
--- a/model/fw/per-fib-limits.cc
+++ b/model/fw/per-fib-limits.cc
@@ -82,6 +82,28 @@
       return false;
     }
 
+  // check stats
+  Ptr<Face> inFace = pitEntry->GetIncoming ().begin ()->m_face;
+  // const ndnSIM::LoadStatsFace &stats = GetStatsTree ()[header->GetName ()].incoming ().find (inFace)->second;
+  const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
+
+  if (stats.count ().GetStats ().get<0> () >= 0.5 * pitEntry->GetFibEntry ()->GetLimits ().GetMaxLimit ())
+  {
+    double ratio = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
+    // NS_ASSERT_MSG (ratio > 0, "If count is a reasonable value, ratio cannot be negative");
+    UniformVariable randAccept (0, 1);
+    double dice = randAccept.GetValue ();
+    if (ratio < 0 || dice < ratio + 0.1)
+      {
+        // ok, accepting the interests
+      }
+    else
+      {
+        // boo. bad luck
+        return false;
+      }
+  }
+  
   if (pitEntry->GetFibEntry ()->GetLimits ().IsBelowLimit ())
     {
       if (outgoingFace->GetLimits ().IsBelowLimit ())
@@ -113,7 +135,7 @@
     }
   
   pitEntry->GetFibEntry ()->GetLimits ().RemoveOutstanding ();
-  pitEntry->GetFibEntry ()->GetLimits ().DecreaseLimit (); // multiplicative decrease
+  // pitEntry->GetFibEntry ()->GetLimits ().DecreaseLimit (); // multiplicative decrease
 
   if (!m_decayLimitsEvent.IsRunning ())
     {
@@ -140,7 +162,7 @@
     }
   
   pitEntry->GetFibEntry ()->GetLimits ().RemoveOutstanding ();
-  pitEntry->GetFibEntry ()->GetLimits ().IncreaseLimit (); // additive increase
+  // pitEntry->GetFibEntry ()->GetLimits ().IncreaseLimit (); // additive increase
 }
 
 
diff --git a/utils/load-stats.cc b/utils/load-stats.cc
index 3bc2897..a7559b3 100644
--- a/utils/load-stats.cc
+++ b/utils/load-stats.cc
@@ -20,6 +20,7 @@
 
 #include "load-stats.h"
 #include "ns3/log.h"
+#include "ns3/simulator.h"
 
 // const double EXP_1  = (1-2.0/6.0);//exp (-1.0/5.0);  /* 1/exp(1sec/5sec) */
 // const double EXP_2  = (1-2.0/31.0);//exp (-1.0/30.0); /* 1/exp(1sec/30sec) */
@@ -40,7 +41,13 @@
 LoadStats::LoadStats ()
   : counter_ (0)
   , avg1_ (0)
+  , avg1Counter_ (0)
+  , avg1CounterOld_ (0)
+
   , avg2_ (0)
+  , avg2Counter_ (0)
+  , avg2CounterOld_ (0)
+
   , avg3_ (0)
 {
 }
@@ -51,9 +58,26 @@
   // NS_LOG_FUNCTION (this);
 
   // do magic
-  avg1_ = EXP_1 * avg1_ + (1 - EXP_1) * counter_;
-  avg2_ = EXP_2 * avg2_ + (1 - EXP_2) * counter_;
-  avg3_ = EXP_3 * avg3_ + (1 - EXP_3) * counter_;
+  // avg1_ = EXP_1 * avg1_ + (1 - EXP_1) * counter_;
+  
+  // highly experimental
+  // avg1Counter_ += counter_;
+  // avg1_ = 1.0 * (avg1Counter_ - avg1CounterOld_) / 1.0/*Seconds(1.0).ToDouble (Time::S)*/;
+  // avg1CounterOld_ = avg1Counter_;
+  // avg1LastUpdate_ = Simulator::Now ();
+  avg1_ = counter_;
+  
+  // avg2_ = EXP_2 * avg2_ + (1 - EXP_2) * counter_;
+
+  avg2Counter_ += counter_;
+  if (Simulator::Now () - avg2LastUpdate_ >= Seconds (5.0))
+    {
+      avg2_ = 1.0 * (avg2Counter_ - avg2CounterOld_) / (Simulator::Now () - avg2LastUpdate_).ToDouble (Time::S);
+      avg2CounterOld_ = avg2Counter_;
+      avg2LastUpdate_ = Simulator::Now ();
+    }
+
+  // avg3_ = EXP_3 * avg3_ + (1 - EXP_3) * counter_;
 
   counter_ = 0;
 }
diff --git a/utils/load-stats.h b/utils/load-stats.h
index 3e71753..816998e 100644
--- a/utils/load-stats.h
+++ b/utils/load-stats.h
@@ -62,10 +62,18 @@
   IsZero () const;
   
 private:
-  uint32_t counter_;
+  uint64_t counter_;
 
   double avg1_;
+  uint64_t avg1Counter_;
+  uint64_t avg1CounterOld_;
+  Time   avg1LastUpdate_;
+  
   double avg2_;
+  uint64_t avg2Counter_;
+  uint64_t avg2CounterOld_;
+  Time   avg2LastUpdate_;
+
   double avg3_;
 
   friend std::ostream &
diff --git a/utils/stats-tree.cc b/utils/stats-tree.cc
index 5893861..f84d902 100644
--- a/utils/stats-tree.cc
+++ b/utils/stats-tree.cc
@@ -130,7 +130,7 @@
       tree_type::point_iterator prune_iterator = item;
       item++;
 
-      prune_iterator->prune ();
+      prune_iterator->prune_node ();
     }
   
   return node->payload ();
diff --git a/utils/trie.h b/utils/trie.h
index a1f9dc7..bcffdc3 100644
--- a/utils/trie.h
+++ b/utils/trie.h
@@ -264,6 +264,22 @@
     return this;
   }
 
+  /**
+   * @brief Perform prune of the node, but without attempting to parent of the node
+   */
+  inline void
+  prune_node ()
+  {
+    if (payload_ == PayloadTraits::empty_payload &&
+        children_.size () == 0)
+      {
+        if (parent_ == 0) return;
+
+        trie *parent = parent_;
+        parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
+      }
+  }
+
   // inline boost::tuple<const iterator, bool, const iterator>
   // find (const FullKey &key) const
   // {