Initial steps in stats tree building. Almost done, but something is fishy
diff --git a/model/ccnx-face.h b/model/ccnx-face.h
index 8bae198..1119ba8 100644
--- a/model/ccnx-face.h
+++ b/model/ccnx-face.h
@@ -208,6 +208,14 @@
*
* Internal index is used for comparison.
*/
+ inline bool
+ operator!= (const CcnxFace &face) const;
+
+ /**
+ * \brief Compare two faces. Only two faces on the same node could be compared.
+ *
+ * Internal index is used for comparison.
+ */
bool
operator< (const CcnxFace &face) const;
@@ -266,6 +274,13 @@
return m_id;
}
+inline bool
+CcnxFace::operator!= (const CcnxFace &face) const
+{
+ return !(*this == face);
+}
+
+
} // namespace ns3
#endif //CCNX_FACE_H
diff --git a/test/ndnSIM-stats-tree.cc b/test/ndnSIM-stats-tree.cc
new file mode 100644
index 0000000..8e522c5
--- /dev/null
+++ b/test/ndnSIM-stats-tree.cc
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,2012 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ndnSIM-stats-tree.h"
+#include "ns3/core-module.h"
+#include "ns3/ndnSIM-module.h"
+#include "../utils/stats-tree.h"
+#include "../apps/ccnx-producer.h"
+
+#include <boost/lexical_cast.hpp>
+
+NS_LOG_COMPONENT_DEFINE ("CcnxStatsTreeTest");
+
+using namespace ndnSIM;
+
+namespace ns3
+{
+
+void
+StatsTreeTest::DoRun ()
+{
+ CcnxStackHelper ccnx;
+
+ Ptr<Node> node1 = CreateObject<Node> ();
+ Ptr<CcnxApp> app1 = CreateObject<CcnxProducer> ();
+ node1->AddApplication (app1);
+ ccnx.Install (node1);
+
+ Ptr<CcnxFace> face1 = CreateObject<CcnxAppFace> (app1);
+ Ptr<CcnxFace> face2 = CreateObject<CcnxAppFace> (app1);
+ Ptr<CcnxFace> face3 = CreateObject<CcnxAppFace> (app1);
+
+ node1->GetObject<Ccnx> ()->AddFace (face1);
+ node1->GetObject<Ccnx> ()->AddFace (face2);
+ node1->GetObject<Ccnx> ()->AddFace (face3);
+
+ NS_LOG_DEBUG (*face1 << ", " << *face2 << ", " << *face3);
+
+ NS_TEST_ASSERT_MSG_NE (*face1, *face2, "Face1 should not be equal to Face2");
+ NS_TEST_ASSERT_MSG_NE (face1, face2, "&Face1 should not be equal to &Face2");
+ NS_TEST_ASSERT_MSG_NE (*face2, *face3, "Face2 should not be equal to Face3");
+ NS_TEST_ASSERT_MSG_NE (face2, face3, "&Face2 should not be equal to &Face3");
+
+ // hack
+ face3->SetId (0);
+ NS_TEST_ASSERT_MSG_EQ (*face1, *face3, "Face1 should be now equal to Face3");
+ NS_TEST_ASSERT_MSG_NE (face1, face3, "&Face1 should not be equal to &Face3");
+
+ LoadStatsNode::stats_container bla;
+ bla[face1].Step ();
+ bla[face2].Step ();
+
+ NS_TEST_ASSERT_MSG_EQ (bla.size (), 2, "Should be two entries in the container");
+
+ bla[face3].Step ();
+ NS_TEST_ASSERT_MSG_EQ (bla.size (), 2, "Should be still two entries in the container");
+
+ LoadStatsNode node;
+ node.AddIncoming (face1);
+ node.AddIncoming (face1);
+ node.AddIncoming (face2);
+ node.AddIncoming (face3);
+
+ NS_TEST_ASSERT_MSG_EQ (node.incoming ().size (), 2, "Incoming should have two entries again");
+ NS_TEST_ASSERT_MSG_EQ (node.outgoing ().size (), 0, "Outgoing should have 0 entries");
+
+ node.Satisfy ();
+ node.Satisfy ();
+ NS_TEST_ASSERT_MSG_EQ (node.incoming ().size (), 2, "Incoming should have two entries again");
+ NS_TEST_ASSERT_MSG_EQ (node.outgoing ().size (), 0, "Outgoing should have 0 entries");
+
+ node.Timeout ();
+ NS_TEST_ASSERT_MSG_EQ (node.incoming ().size (), 2, "Incoming should have two entries again");
+ NS_TEST_ASSERT_MSG_EQ (node.outgoing ().size (), 0, "Outgoing should have 0 entries");
+
+ NS_LOG_DEBUG ("count: " << node.incoming ().find (face1)->second.count ());
+ NS_LOG_DEBUG ("satisfied: " << node.incoming ().find (face1)->second.satisfied ());
+ NS_LOG_DEBUG ("unsatisfied:" << node.incoming ().find (face1)->second.unsatisfied ());
+
+ node.Step ();
+
+ NS_LOG_DEBUG ("count: " << node.incoming ().find (face1)->second.count ());
+ NS_LOG_DEBUG ("satisfied: " << node.incoming ().find (face1)->second.satisfied ());
+ NS_LOG_DEBUG ("unsatisfied:" << node.incoming ().find (face1)->second.unsatisfied ());
+
+ LoadStats::stats_tuple tuple = node.incoming ().find (face1)->second.GetSatisfiedRatio ();
+ NS_LOG_DEBUG ("In, face1, satisfied ratio: " << tuple.get<0> () << ", " << tuple.get<1> () << ", " << tuple.get<2> ());
+
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<0> (), 0.667, 0.01, "Satisfied ratio should be ~ 2/3");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<1> (), 0.667, 0.01, "Satisfied ratio should be ~ 2/3");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<2> (), 0.667, 0.01, "Satisfied ratio should be ~ 2/3");
+
+ tuple = node.incoming ().find (face1)->second.GetUnsatisfiedRatio ();
+ NS_LOG_DEBUG ("In, face1, unsatisfied ratio: " << tuple.get<0> () << ", " << tuple.get<1> () << ", " << tuple.get<2> ());
+
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<0> (), 0.333, 0.01, "Satisfied ratio should be ~ 1/3");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<1> (), 0.333, 0.01, "Satisfied ratio should be ~ 1/3");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<2> (), 0.333, 0.01, "Satisfied ratio should be ~ 1/3");
+
+ node.AddIncoming (face1);
+ node.Timeout ();
+ node.Step ();
+
+ NS_LOG_DEBUG ("After decaying");
+
+ tuple = node.incoming ().find (face1)->second.GetSatisfiedRatio ();
+ NS_LOG_DEBUG ("In, face1, satisfied ratio: " << tuple.get<0> () << ", " << tuple.get<1> () << ", " << tuple.get<2> ());
+
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<0> (), 0.489, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<1> (), 0.489, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<2> (), 0.489, 0.01, "");
+
+ tuple = node.incoming ().find (face1)->second.GetUnsatisfiedRatio ();
+ NS_LOG_DEBUG ("In, face1, unsatisfied ratio: " << tuple.get<0> () << ", " << tuple.get<1> () << ", " << tuple.get<2> ());
+
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<0> (), 0.51, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<1> (), 0.51, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<2> (), 0.51, 0.01, "");
+
+ for (uint32_t i = 0; i < 50; i++ )
+ node.Step ();
+
+ NS_LOG_DEBUG ("After more decaying");
+
+ tuple = node.incoming ().find (face1)->second.GetSatisfiedRatio ();
+ NS_LOG_DEBUG ("In, face1, satisfied ratio: " << tuple.get<0> () << ", " << tuple.get<1> () << ", " << tuple.get<2> ());
+
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<0> (), 0.228, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<1> (), 0.047, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<2> (), 0.015, 0.01, "");
+
+ tuple = node.incoming ().find (face1)->second.GetUnsatisfiedRatio ();
+ NS_LOG_DEBUG ("In, face1, unsatisfied ratio: " << tuple.get<0> () << ", " << tuple.get<1> () << ", " << tuple.get<2> ());
+
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<0> (), 0.238, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<1> (), 0.049, 0.01, "");
+ NS_TEST_ASSERT_MSG_EQ_TOL (tuple.get<2> (), 0.016, 0.01, "");
+
+ /////////////////////////////////////////////////////
+ // Actual tree testing //
+ /////////////////////////////////////////////////////
+
+ StatsTree tree;
+ tree.NewPitEntry (CcnxNameComponents ("/bla/bla/bla"));
+ tree.NewPitEntry (CcnxNameComponents ("/foo/bar"));
+ tree.NewPitEntry (CcnxNameComponents ("/bar/foo"));
+ tree.NewPitEntry (CcnxNameComponents ("/tra/la/la"));
+
+ tree.Incoming (CcnxNameComponents ("/bla/bla/bla"), face1);
+ tree.Outgoing (CcnxNameComponents ("/foo/bar"), face2);
+ tree.Satisfy (CcnxNameComponents ("/bar/foo"));
+ tree.Satisfy (CcnxNameComponents ("/tra/la/la"));
+
+ tree.Step ();
+
+ NS_LOG_DEBUG (tree);
+}
+
+}
diff --git a/test/ndnSIM-stats-tree.h b/test/ndnSIM-stats-tree.h
new file mode 100644
index 0000000..504257c
--- /dev/null
+++ b/test/ndnSIM-stats-tree.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDNSIM_TEST_STATS_TREE_H
+#define NDNSIM_TEST_STATS_TREE_H
+
+#include "ns3/test.h"
+#include "ns3/ptr.h"
+
+namespace ns3
+{
+
+class StatsTreeTest : public TestCase
+{
+public:
+ StatsTreeTest ()
+ : TestCase ("StatsTree test")
+ {
+ }
+
+private:
+ virtual void DoRun ();
+};
+
+}
+
+#endif // NDNSIM_TEST_STATS_TREE_H
diff --git a/test/ndnSIM-tests.cc b/test/ndnSIM-tests.cc
index 004f761..e62dc19 100644
--- a/test/ndnSIM-tests.cc
+++ b/test/ndnSIM-tests.cc
@@ -23,6 +23,7 @@
#include "ndnSIM-serialization.h"
#include "ndnSIM-pit.h"
+#include "ndnSIM-stats-tree.h"
namespace ns3
{
@@ -38,6 +39,7 @@
AddTestCase (new InterestSerializationTest ());
AddTestCase (new ContentObjectSerializationTest ());
AddTestCase (new PitTest ());
+ AddTestCase (new StatsTreeTest ());
}
};
diff --git a/utils/load-stats-face.cc b/utils/load-stats-face.cc
new file mode 100644
index 0000000..834004a
--- /dev/null
+++ b/utils/load-stats-face.cc
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "load-stats-face.h"
+
+namespace ndnSIM
+{
+
+void
+LoadStatsFace::Step ()
+{
+ m_count.Step ();
+ m_satisfied.Step ();
+ m_unsatisfied.Step ();
+}
+
+//
+LoadStats::stats_tuple
+LoadStatsFace::GetSatisfiedRatio () const
+{
+ return LoadStats::stats_tuple (m_satisfied.GetStats ().get<0> () / std::max (0.01, m_count.GetStats ().get<0> ()),
+ m_satisfied.GetStats ().get<1> () / std::max (0.01, m_count.GetStats ().get<1> ()),
+ m_satisfied.GetStats ().get<2> () / std::max (0.01, m_count.GetStats ().get<2> ()));
+}
+
+LoadStats::stats_tuple
+LoadStatsFace::GetUnsatisfiedRatio () const
+{
+ return LoadStats::stats_tuple (m_unsatisfied.GetStats ().get<0> () / std::max (0.01, m_count.GetStats ().get<0> ()),
+ m_unsatisfied.GetStats ().get<1> () / std::max (0.01, m_count.GetStats ().get<1> ()),
+ m_unsatisfied.GetStats ().get<2> () / std::max (0.01, m_count.GetStats ().get<2> ()));
+}
+
+LoadStatsFace &
+LoadStatsFace::operator += (const LoadStatsFace &load)
+{
+ m_count += load.m_count;
+ m_satisfied += load.m_satisfied;
+ m_unsatisfied += load.m_unsatisfied;
+
+ return *this;
+}
+
+std::ostream &
+operator << (std::ostream &os, const LoadStatsFace &stats)
+{
+ os << stats.m_count << "/" << stats.m_satisfied << "/" << stats.m_unsatisfied;
+ return os;
+}
+
+}
diff --git a/utils/load-stats-face.h b/utils/load-stats-face.h
new file mode 100644
index 0000000..ad033b4
--- /dev/null
+++ b/utils/load-stats-face.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef LOAD_STATS_FACE_H
+#define LOAD_STATS_FACE_H
+
+#include "load-stats.h"
+
+namespace ndnSIM
+{
+
+class LoadStatsFace
+{
+public:
+ void
+ Step ();
+
+ inline LoadStats&
+ count ();
+
+ inline const LoadStats&
+ count () const;
+
+ inline LoadStats&
+ satisfied ();
+
+ inline const LoadStats&
+ satisfied () const;
+
+ inline LoadStats&
+ unsatisfied ();
+
+ inline const LoadStats&
+ unsatisfied () const;
+
+ //
+ LoadStats::stats_tuple
+ GetSatisfiedRatio () const;
+
+ LoadStats::stats_tuple
+ GetUnsatisfiedRatio () const;
+
+ LoadStatsFace &
+ operator += (const LoadStatsFace &load);
+
+private:
+ LoadStats m_count;
+ LoadStats m_satisfied;
+ LoadStats m_unsatisfied;
+
+ friend std::ostream &
+ operator << (std::ostream &os, const LoadStatsFace &stats);
+};
+
+inline LoadStats&
+LoadStatsFace::count ()
+{ return m_count; }
+
+inline const LoadStats&
+LoadStatsFace::count () const
+{ return m_count; }
+
+inline LoadStats&
+LoadStatsFace::satisfied ()
+{ return m_satisfied; }
+
+inline const LoadStats&
+LoadStatsFace::satisfied () const
+{ return m_satisfied; }
+
+inline LoadStats&
+LoadStatsFace::unsatisfied ()
+{ return m_unsatisfied; }
+
+inline const LoadStats&
+LoadStatsFace::unsatisfied () const
+{ return m_unsatisfied; }
+
+std::ostream &
+operator << (std::ostream &os, const LoadStatsFace &stats);
+
+}
+
+#endif // LOAD_STATS_FACE_H
diff --git a/utils/load-stats-node.cc b/utils/load-stats-node.cc
new file mode 100644
index 0000000..34875c5
--- /dev/null
+++ b/utils/load-stats-node.cc
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "load-stats-node.h"
+#include "ns3/ccnx-face.h"
+
+using namespace ns3;
+
+namespace ndnSIM
+{
+
+void
+LoadStatsNode::Step ()
+{
+ m_pit.Step ();
+
+ for (stats_container::iterator item = m_incoming.begin ();
+ item != m_incoming.end ();
+ item ++)
+ {
+ item->second.Step ();
+ }
+
+ for (stats_container::iterator item = m_outgoing.begin ();
+ item != m_outgoing.end ();
+ item ++)
+ {
+ item->second.Step ();
+ }
+}
+
+void
+LoadStatsNode::NewPitEntry ()
+{
+ m_pit.count ()++;
+}
+
+void
+LoadStatsNode::AddIncoming (ns3::Ptr<ns3::CcnxFace> face)
+{
+ m_incoming [face].count ()++;
+}
+
+void
+LoadStatsNode::AddOutgoing (ns3::Ptr<ns3::CcnxFace> face)
+{
+ m_outgoing [face].count ()++;
+}
+
+void
+LoadStatsNode::Satisfy ()
+{
+ m_pit.satisfied ()++;
+
+ for (stats_container::iterator item = m_incoming.begin ();
+ item != m_incoming.end ();
+ item ++)
+ {
+ item->second.satisfied ()++;
+ }
+
+ for (stats_container::iterator item = m_outgoing.begin ();
+ item != m_outgoing.end ();
+ item ++)
+ {
+ item->second.satisfied ()++;
+ }
+}
+
+void
+LoadStatsNode::Timeout ()
+{
+ m_pit.unsatisfied ()++;
+
+ for (stats_container::iterator item = m_incoming.begin ();
+ item != m_incoming.end ();
+ item ++)
+ {
+ item->second.unsatisfied ()++;
+ }
+
+ for (stats_container::iterator item = m_outgoing.begin ();
+ item != m_outgoing.end ();
+ item ++)
+ {
+ item->second.unsatisfied ()++;
+ }
+}
+
+LoadStatsNode &
+LoadStatsNode::operator += (const LoadStatsNode &stats)
+{
+ m_pit += stats.m_pit;
+
+ // aggregate incoming
+ for (stats_container::const_iterator item = stats.m_incoming.begin ();
+ item != stats.m_incoming.end ();
+ item ++)
+ {
+ m_incoming [item->first] += item->second;
+ }
+
+ // aggregate outgoing
+ for (stats_container::const_iterator item = stats.m_outgoing.begin ();
+ item != stats.m_outgoing.end ();
+ item ++)
+ {
+ m_outgoing [item->first] += item->second;
+ }
+
+ return *this;
+}
+
+std::ostream&
+operator << (std::ostream &os, const LoadStatsNode &node)
+{
+ os << "PIT: " << node.m_pit << std::endl;
+ return os;
+}
+
+
+}
diff --git a/utils/load-stats-node.h b/utils/load-stats-node.h
new file mode 100644
index 0000000..5376144
--- /dev/null
+++ b/utils/load-stats-node.h
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef LOAD_STATS_NODE_H
+#define LOAD_STATS_NODE_H
+
+#include "load-stats-face.h"
+#include <map>
+#include "ns3/ptr.h"
+
+namespace ns3
+{
+class CcnxFace;
+}
+
+namespace ndnSIM
+{
+
+// this thing is actually put into a tree node, associated with each "name entry"
+
+class LoadStatsNode
+{
+public:
+ typedef std::map< ns3::Ptr<ns3::CcnxFace>, LoadStatsFace > stats_container;
+
+ LoadStatsNode () {}
+ LoadStatsNode (const LoadStatsNode &) {}
+
+ void
+ Step ();
+
+ /**
+ * Increment face-independent counter
+ */
+ void
+ NewPitEntry ();
+
+ /**
+ * Increment counter to incoming list
+ */
+ void
+ AddIncoming (ns3::Ptr<ns3::CcnxFace> face);
+
+ /**
+ * Increment counter to outgoing list
+ */
+ void
+ AddOutgoing (ns3::Ptr<ns3::CcnxFace> face);
+
+ /**
+ * Increment counter to both incoming and outgoing lists, for all faces
+ */
+ void
+ Satisfy ();
+
+ /**
+ * Increment counter to both incoming and outgoing lists, for all faces
+ */
+ void
+ Timeout ();
+
+ LoadStatsNode &
+ operator += (const LoadStatsNode &stats);
+
+ inline const stats_container &
+ incoming () const;
+
+ inline const stats_container &
+ outgoing () const;
+
+ inline const LoadStatsFace &
+ pit () const;
+
+ bool
+ operator == (const LoadStatsNode &other) const
+ {
+ return false;
+ }
+
+ bool
+ operator != (const LoadStatsNode &other) const
+ {
+ return true;
+ }
+
+ LoadStatsNode &
+ operator = (const LoadStatsNode &other)
+ {
+ // don't do any copying at all
+ return *this;
+ }
+
+private:
+ LoadStatsFace m_pit;
+ stats_container m_incoming;
+ stats_container m_outgoing;
+
+ friend std::ostream&
+ operator << (std::ostream &os, const LoadStatsNode &node);
+};
+
+inline const LoadStatsNode::stats_container &
+LoadStatsNode::incoming () const
+{
+ return m_incoming;
+}
+
+inline const LoadStatsNode::stats_container &
+LoadStatsNode::outgoing () const
+{
+ return m_outgoing;
+}
+
+inline const LoadStatsFace &
+LoadStatsNode::pit () const
+{
+ return m_pit;
+}
+
+std::ostream&
+operator << (std::ostream &os, const LoadStatsNode &node);
+
+}
+
+#endif
diff --git a/utils/load-stats.cc b/utils/load-stats.cc
new file mode 100644
index 0000000..ee61df4
--- /dev/null
+++ b/utils/load-stats.cc
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "load-stats.h"
+
+using namespace ns3;
+
+const double EXP_1 = exp (-5.0/60.0); /* 1/exp(5sec/1min) */
+const double EXP_5 = exp (-5.0/300.0); /* 1/exp(5sec/5min) */
+const double EXP_15 = exp (-5.0/900.0); /* 1/exp(5sec/15min) */
+
+const double EPSILON = 0.000001;
+
+namespace ndnSIM
+{
+
+LoadStats::LoadStats ()
+ : counter_ (0)
+ , avg1_ (0)
+ , avg5_ (0)
+ , avg15_ (0)
+{
+}
+
+void
+LoadStats::Step ()
+{
+ // do magic
+ avg1_ = EXP_1 * avg1_ + (1 - EXP_1) * counter_;
+ avg5_ = EXP_1 * avg5_ + (1 - EXP_5) * counter_;
+ avg15_ = EXP_1 * avg15_ + (1 - EXP_15) * counter_;
+
+ counter_ = 0;
+}
+
+LoadStats &
+LoadStats::operator ++ (int)
+{
+ counter_ ++;
+ return *this;
+}
+
+// void
+// LoadStats::Increment (uint32_t amount)
+// {
+// counter_ += amount;
+// }
+
+// uint32_t
+// LoadStats::GetCounter () const
+// {
+// return counter_;
+// }
+
+LoadStats &
+LoadStats::operator += (const LoadStats &stats)
+{
+ counter_ += stats.counter_;
+ return *this;
+}
+
+LoadStats::stats_tuple
+LoadStats::GetStats () const
+{
+ return stats_tuple (avg1_, avg5_, avg15_);
+}
+
+bool
+LoadStats::IsEmpty () const
+{
+ return (avg1_ < EPSILON &&
+ avg5_ < EPSILON &&
+ avg15_ < EPSILON);
+}
+
+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;
+ return os;
+}
+
+} // ndnSIM
diff --git a/utils/load-stats.h b/utils/load-stats.h
new file mode 100644
index 0000000..8b2433e
--- /dev/null
+++ b/utils/load-stats.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef LOAD_STATS_H
+#define LOAD_STATS_H
+
+#include "ns3/nstime.h"
+#include <boost/tuple/tuple.hpp>
+
+namespace ndnSIM
+{
+
+class LoadStats
+{
+public:
+ typedef boost::tuple<double, double, double> stats_tuple;
+
+ LoadStats ();
+
+ void
+ Step ();
+
+ // void
+ // Increment (uint32_t amount);
+
+ LoadStats &
+ operator ++ (int);
+
+ // uint32_t
+ // GetCounter () const;
+
+ LoadStats &
+ operator += (const LoadStats &stats);
+
+ stats_tuple
+ GetStats () const;
+
+ bool
+ IsEmpty () const;
+
+private:
+ uint32_t counter_;
+
+ double avg1_;
+ double avg5_;
+ double avg15_;
+};
+
+std::ostream &
+operator << (std::ostream &os, const LoadStats &stats);
+
+} // ndnSIM
+
+#endif // LOAD_STATS_H
diff --git a/utils/stats-tree.cc b/utils/stats-tree.cc
new file mode 100644
index 0000000..eb37c02
--- /dev/null
+++ b/utils/stats-tree.cc
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "stats-tree.h"
+#include "ns3/ccnx-face.h"
+#include "ns3/log.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("StatsTree");
+
+namespace ndnSIM
+{
+
+StatsTree::StatsTree ()
+ : m_tree ("")
+{
+}
+
+void
+StatsTree::Step ()
+{
+ // walking the tree, aggregating and stepping on every node, starting the leaves
+ // for (trie_type::
+
+ WalkLeftRightRoot (&m_tree);
+}
+
+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);
+}
+
+void
+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);
+}
+
+void
+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 ();
+}
+
+void
+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
+{
+ 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 ();
+}
+
+const LoadStatsNode&
+StatsTree::WalkLeftRightRoot (tree_type *node)
+{
+ tree_type::point_iterator item (*node), end;
+
+ for (; item != end; item++)
+ {
+ node->payload () += WalkLeftRightRoot (&*item);
+ NS_LOG_DEBUG (node << ", " << node->payload ());
+ }
+
+ node->payload ().Step ();
+ return node->payload ();
+}
+
+std::ostream &
+operator << (std::ostream &os, const StatsTree &tree)
+{
+ os << tree.m_tree.payload ();
+ return os;
+}
+
+
+}
diff --git a/utils/stats-tree.h b/utils/stats-tree.h
new file mode 100644
index 0000000..e731d32
--- /dev/null
+++ b/utils/stats-tree.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef STATS_TREE_H
+#define STATS_TREE_H
+
+#include "trie.h"
+#include "load-stats-node.h"
+#include "ns3/ccnx-name-components.h"
+#include "ns3/ptr.h"
+
+namespace ndnSIM
+{
+
+class StatsTree
+{
+public:
+ typedef trie< ns3::CcnxNameComponents,
+ non_pointer_traits< LoadStatsNode >, void* > tree_type;
+
+ StatsTree ();
+
+ void
+ Step ();
+
+ void
+ NewPitEntry (const ns3::CcnxNameComponents &key);
+
+ void
+ Incoming (const ns3::CcnxNameComponents &key, ns3::Ptr<ns3::CcnxFace> face);
+
+ void
+ Outgoing (const ns3::CcnxNameComponents &key, ns3::Ptr<ns3::CcnxFace> face);
+
+ void
+ Satisfy (const ns3::CcnxNameComponents &key);
+
+ void
+ Timeout (const ns3::CcnxNameComponents &key);
+
+ const LoadStatsNode &
+ Get (const ns3::CcnxNameComponents &key) const;
+
+private:
+ const LoadStatsNode &
+ WalkLeftRightRoot (tree_type *node);
+
+private:
+ tree_type m_tree;
+
+ friend std::ostream &
+ operator << (std::ostream &os, const StatsTree &tree);
+};
+
+std::ostream &
+operator << (std::ostream &os, const StatsTree &tree);
+
+} // ndnSIM
+
+#endif // STATS_TREE_H
diff --git a/utils/trie-with-policy.h b/utils/trie-with-policy.h
index ea194b3..bb5a668 100644
--- a/utils/trie-with-policy.h
+++ b/utils/trie-with-policy.h
@@ -53,7 +53,7 @@
}
inline std::pair< iterator, bool >
- insert (const FullKey &key, typename PayloadTraits::pointer_type payload)
+ insert (const FullKey &key, typename PayloadTraits::insert_type payload)
{
std::pair<iterator, bool> item =
trie_.insert (key, payload);
diff --git a/utils/trie.h b/utils/trie.h
index 50288af..51a7678 100644
--- a/utils/trie.h
+++ b/utils/trie.h
@@ -41,9 +41,12 @@
template<typename Payload>
struct pointer_payload_traits
{
- typedef Payload payload_type;
- typedef Payload* pointer_type;
- typedef const Payload* const_pointer_type;
+ typedef Payload payload_type; // general type of the payload
+ typedef Payload* storage_type; // how the payload is actually stored
+ typedef Payload* insert_type; // what parameter is inserted
+
+ typedef Payload* return_type; // what is returned on access
+ typedef const Payload* const_return_type; // what is returned on const access
static Payload* empty_payload;
};
@@ -56,8 +59,11 @@
struct smart_pointer_payload_traits
{
typedef Payload payload_type;
- typedef ns3::Ptr<Payload> pointer_type;
- typedef ns3::Ptr<const Payload> const_pointer_type;
+ typedef ns3::Ptr<Payload> storage_type;
+ typedef ns3::Ptr<Payload> insert_type;
+
+ typedef ns3::Ptr<Payload> return_type;
+ typedef ns3::Ptr<const Payload> const_return_type;
static ns3::Ptr<Payload> empty_payload;
};
@@ -66,6 +72,23 @@
ns3::Ptr<Payload>
smart_pointer_payload_traits<Payload>::empty_payload = 0;
+template<typename Payload>
+struct non_pointer_traits
+{
+ typedef Payload payload_type;
+ typedef Payload storage_type;
+ typedef const Payload & insert_type; // nothing to insert
+
+ typedef Payload& return_type;
+ typedef const Payload & const_return_type;
+
+ static Payload empty_payload;
+};
+
+template<typename Payload>
+Payload
+non_pointer_traits<Payload>::empty_payload = Payload ();
+
////////////////////////////////////////////////////
// forward declarations
@@ -95,6 +118,9 @@
template<class T>
class trie_iterator;
+template<class T>
+class trie_point_iterator;
+
template<typename FullKey,
typename PayloadTraits,
typename PolicyHook >
@@ -109,6 +135,9 @@
typedef trie_iterator<trie> recursive_iterator;
typedef trie_iterator<const trie> const_recursive_iterator;
+ typedef trie_point_iterator<trie> point_iterator;
+ typedef trie_point_iterator<const trie> const_point_iterator;
+
typedef PayloadTraits payload_traits;
inline
@@ -164,7 +193,7 @@
inline std::pair<iterator, bool>
insert (const FullKey &key,
- typename PayloadTraits::pointer_type payload)
+ typename PayloadTraits::insert_type payload)
{
trie *trieNode = this;
@@ -331,20 +360,20 @@
return 0;
}
- typename PayloadTraits::const_pointer_type
+ typename PayloadTraits::const_return_type
payload () const
{
return payload_;
}
- typename PayloadTraits::pointer_type
+ typename PayloadTraits::return_type
payload ()
{
return payload_;
}
void
- set_payload (typename PayloadTraits::pointer_type payload)
+ set_payload (typename PayloadTraits::insert_type payload)
{
payload_ = payload;
}
@@ -393,7 +422,10 @@
template<class T>
friend class trie_iterator;
-
+
+ template<class T>
+ friend class trie_point_iterator;
+
////////////////////////////////////////////////
// Actual data
////////////////////////////////////////////////
@@ -408,7 +440,7 @@
buckets_array buckets_;
unordered_set children_;
- typename PayloadTraits::pointer_type payload_;
+ typename PayloadTraits::storage_type payload_;
trie *parent_; // to make cleaning effective
};
@@ -419,7 +451,7 @@
inline std::ostream&
operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
{
- os << "# " << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << std::endl;
+ os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
@@ -427,8 +459,8 @@
subnode++ )
// BOOST_FOREACH (const trie &subnode, trie_node.children_)
{
- os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << "\"]\n";
- os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != 0)?"*":"") << "\"]""\n";
+ os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
+ os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
os << *subnode;
@@ -442,7 +474,7 @@
trie<FullKey, PayloadTraits, PolicyHook>
::PrintStat (std::ostream &os) const
{
- os << "# " << key_ << ((payload_ != 0)?"*":"") << ": " << children_.size() << " children" << std::endl;
+ os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
for (size_t bucket = 0, maxbucket = children_.bucket_count ();
bucket < maxbucket;
bucket++)
@@ -543,6 +575,65 @@
};
+template<class Trie>
+class trie_point_iterator
+{
+private:
+ typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
+ typename Trie::unordered_set::const_iterator,
+ typename Trie::unordered_set::iterator>::type set_iterator;
+
+public:
+ trie_point_iterator () : trie_ (0) {}
+ trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
+ trie_point_iterator (Trie &item)
+ {
+ if (item.children_.size () != 0)
+ trie_ = &*item.children_.begin ();
+ else
+ trie_ = 0;
+ }
+
+ Trie & operator* () { return *trie_; }
+ const Trie & operator* () const { return *trie_; }
+ Trie * operator-> () { return trie_; }
+ const Trie * operator-> () const { return trie_; }
+ bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
+ bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
+ bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
+ bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
+
+ trie_point_iterator<Trie> &
+ operator++ (int)
+ {
+ if (trie_->parent_ != 0)
+ {
+ set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
+ item ++;
+ if (item == trie_->parent_->children_.end ())
+ trie_ = 0;
+ else
+ trie_ = &*item;
+ }
+ else
+ {
+ trie_ = 0;
+ }
+ return *this;
+ }
+
+ trie_point_iterator<Trie> &
+ operator++ ()
+ {
+ (*this)++;
+ return *this;
+ }
+
+private:
+ Trie *trie_;
+};
+
+
} // ndnSIM
#endif // TRIE_H_