src/common/composite-trace-resolver.cc
changeset 1421 df273f351a4c
parent 1323 08174b13d76f
parent 1420 3feedd3e4f5f
child 1422 d40dfd686fc3
equal deleted inserted replaced
1323:08174b13d76f 1421:df273f351a4c
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2007 INRIA
       
     4  * All rights reserved.
       
     5  *
       
     6  * This program is free software; you can redistribute it and/or modify
       
     7  * it under the terms of the GNU General Public License version 2 as
       
     8  * published by the Free Software Foundation;
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License
       
    16  * along with this program; if not, write to the Free Software
       
    17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    18  *
       
    19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    20  */
       
    21 #include "composite-trace-resolver.h"
       
    22 
       
    23 namespace ns3 {
       
    24 
       
    25 CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context)
       
    26   : TraceResolver (context)
       
    27 {}
       
    28 
       
    29 CompositeTraceResolver::~CompositeTraceResolver ()
       
    30 {}
       
    31 
       
    32 void 
       
    33 CompositeTraceResolver::Add (std::string name, 
       
    34                              Callback<TraceResolver *,TraceContext const &> createResolver)
       
    35 {
       
    36   TraceContext traceContext = GetContext ();
       
    37   DoAdd (name, createResolver, traceContext);
       
    38 }
       
    39 
       
    40 void 
       
    41 CompositeTraceResolver::DoAdd (std::string name, 
       
    42 			       Callback<TraceResolver *,TraceContext const &> createResolver,
       
    43 			       TraceContext const &context)
       
    44 {
       
    45   struct CallbackTraceSourceItem item;
       
    46   item.name = name;
       
    47   item.createResolver = createResolver;
       
    48   item.context = context;
       
    49   m_items.push_back (item);
       
    50 }
       
    51 
       
    52 TraceResolver::TraceResolverList 
       
    53 CompositeTraceResolver::DoLookup (std::string id) const
       
    54 {
       
    55   if (id == "*")
       
    56     {
       
    57       TraceResolver::TraceResolverList list;
       
    58       for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
       
    59 	{
       
    60 	  list.push_back (i->createResolver (i->context));
       
    61 	}
       
    62       return list;
       
    63     }
       
    64   std::string::size_type start, end;
       
    65   start = id.find_first_of ("(", 0);
       
    66   end = id.find_first_of (")", 0);
       
    67   if (start != 0 || end != (id.size ()-1))
       
    68     {
       
    69       for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
       
    70 	{
       
    71 	  if (i->name == id)
       
    72 	    {
       
    73 	      TraceResolver::TraceResolverList list;
       
    74 	      list.push_back (i->createResolver (i->context));
       
    75 	      return list;
       
    76 	    }
       
    77 	}
       
    78     }
       
    79   std::list<std::string> names;
       
    80   std::string alternatives = std::string (id, start+1, end-1);
       
    81   std::string::size_type next, cur;
       
    82   next = 0;
       
    83   cur = 0;
       
    84   while (true)
       
    85     {
       
    86       std::string element;
       
    87       next = alternatives.find ("|", cur);
       
    88       if (next == std::string::npos)
       
    89 	{
       
    90 	  element = std::string (alternatives, cur, alternatives.size ());
       
    91 	  names.push_back (element);
       
    92 	  break;
       
    93 	}
       
    94       element = std::string (alternatives, cur, next);
       
    95       names.push_back (element);
       
    96       cur = next + 1;
       
    97     }
       
    98   TraceResolver::TraceResolverList list;
       
    99   for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++)
       
   100     {
       
   101       for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++)
       
   102 	{
       
   103 	  if (j->name == *i)
       
   104 	    {
       
   105 	      list.push_back (j->createResolver (j->context));
       
   106 	      break;
       
   107 	    }
       
   108 	}
       
   109     }
       
   110   return list;
       
   111 }
       
   112 
       
   113 }//namespace ns3
       
   114 
       
   115 #ifdef RUN_SELF_TESTS
       
   116 
       
   117 #include "ns3/test.h"
       
   118 #include "trace-context-element.h"
       
   119 
       
   120 namespace ns3 {
       
   121 
       
   122 class TraceSourceTest : public TraceContextElement
       
   123 {
       
   124 public:
       
   125   enum Sources {
       
   126     DOUBLEA,
       
   127     DOUBLEB,
       
   128     SUBRESOLVER,
       
   129   };
       
   130   static uint16_t GetUid (void) 
       
   131   {static uint16_t uid = AllocateUid<TraceSourceTest> ("TraceSourceTest"); return uid;}
       
   132   void Print (std::ostream &os)
       
   133   {os << "tracesource=";
       
   134     if (m_sources == DOUBLEA) {os << "doubleA";}
       
   135     else if (m_sources == DOUBLEB) {os << "doubleB";}
       
   136     else if (m_sources == SUBRESOLVER) {os << "subresolver";}
       
   137   }
       
   138   TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {}
       
   139   TraceSourceTest (enum Sources sources) :m_sources (sources) {}
       
   140   bool IsDoubleA (void) {return m_sources == TraceSourceTest::DOUBLEA;}
       
   141   bool IsDoubleB (void) {return m_sources == TraceSourceTest::DOUBLEB;}
       
   142 private:
       
   143   enum TraceSourceTest::Sources m_sources;
       
   144 };
       
   145 
       
   146 class SubTraceSourceTest : public TraceContextElement
       
   147 {
       
   148 public:
       
   149   enum Sources {
       
   150     INT,
       
   151   };
       
   152   static uint16_t GetUid (void) 
       
   153   {static uint16_t uid = AllocateUid<SubTraceSourceTest> ("SubTraceSourceTest"); return uid;}
       
   154   void Print (std::ostream &os)
       
   155   {os << "subtracesource=int";}
       
   156   SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {}
       
   157   SubTraceSourceTest (enum Sources sources) : m_sources (sources) {}
       
   158 private:
       
   159   enum Sources m_sources;
       
   160 };
       
   161 
       
   162 class CompositeTraceResolverTest : public Test
       
   163 {
       
   164 public:
       
   165   CompositeTraceResolverTest ();
       
   166   virtual ~CompositeTraceResolverTest ();
       
   167   virtual bool RunTests (void);
       
   168 private:
       
   169   void TraceDouble (TraceContext const &context, double v);
       
   170   void TraceInt (TraceContext const &context, int v);
       
   171   TraceResolver *CreateSubResolver (TraceContext const &context);
       
   172 
       
   173 
       
   174   bool m_gotDoubleA;
       
   175   bool m_gotDoubleB;
       
   176   CallbackTraceSource<int> m_traceInt;
       
   177   bool m_gotInt;
       
   178 };
       
   179 
       
   180 CompositeTraceResolverTest::CompositeTraceResolverTest ()
       
   181   : Test ("CompositeTraceResolver")
       
   182 {}
       
   183 CompositeTraceResolverTest::~CompositeTraceResolverTest ()
       
   184 {}
       
   185 void 
       
   186 CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
       
   187 {
       
   188   TraceSourceTest source;
       
   189   context.Get (source);
       
   190   if (source.IsDoubleA ())
       
   191     {
       
   192       m_gotDoubleA = true;
       
   193     }
       
   194   else if (source.IsDoubleB ())
       
   195     {
       
   196       m_gotDoubleB = true;
       
   197     }
       
   198   else
       
   199     {
       
   200       NS_FATAL_ERROR ("should not get any other trace source in this sink");
       
   201     }
       
   202   
       
   203 }
       
   204 
       
   205 void 
       
   206 CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v)
       
   207 {
       
   208   m_gotInt = true;
       
   209 }
       
   210 
       
   211 TraceResolver *
       
   212 CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context)
       
   213 {
       
   214   CompositeTraceResolver *subresolver = new CompositeTraceResolver (context);
       
   215   subresolver->Add ("trace-int", m_traceInt, 
       
   216                     SubTraceSourceTest (SubTraceSourceTest::INT));
       
   217   return subresolver;
       
   218 }
       
   219 bool 
       
   220 CompositeTraceResolverTest::RunTests (void)
       
   221 {
       
   222   bool ok = true;
       
   223 
       
   224   CallbackTraceSource<double> traceDoubleA;
       
   225   CallbackTraceSource<double> traceDoubleB;
       
   226   TraceContext context;
       
   227 
       
   228   CompositeTraceResolver resolver (context) ;
       
   229 
       
   230   resolver.Add ("trace-double-a", traceDoubleA, 
       
   231                 TraceSourceTest (TraceSourceTest::DOUBLEA));
       
   232   resolver.Add ("trace-double-b", traceDoubleB, 
       
   233                 TraceSourceTest (TraceSourceTest::DOUBLEB));
       
   234 
       
   235   resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   236 
       
   237   m_gotDoubleA = false;
       
   238   m_gotDoubleB = false;
       
   239   traceDoubleA (0);
       
   240   if (!m_gotDoubleA || m_gotDoubleB)
       
   241     {
       
   242       ok = false;
       
   243     }
       
   244   m_gotDoubleA = false;
       
   245   traceDoubleA (0);
       
   246   traceDoubleB (0);
       
   247   if (!m_gotDoubleA || !m_gotDoubleB)
       
   248     {
       
   249       ok = false;
       
   250     }
       
   251   m_gotDoubleA = false;
       
   252   m_gotDoubleB = false;
       
   253 
       
   254   resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   255 
       
   256   m_gotDoubleA = false;
       
   257   m_gotDoubleB = false;
       
   258   traceDoubleA (0);
       
   259   traceDoubleB (0);
       
   260   if (m_gotDoubleA || m_gotDoubleB)
       
   261     {
       
   262       ok = false;
       
   263     }
       
   264 
       
   265   resolver.Connect ("/trace-double-a", 
       
   266 		    MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   267   m_gotDoubleA = false;
       
   268   m_gotDoubleB = false;
       
   269   traceDoubleA (0);
       
   270   traceDoubleB (0);
       
   271   if (!m_gotDoubleA || m_gotDoubleB)
       
   272     {
       
   273       ok = false;
       
   274     }
       
   275   resolver.Disconnect ("/trace-double-a", 
       
   276 		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   277 
       
   278   resolver.Connect ("/(trace-double-a)", 
       
   279 		    MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   280   m_gotDoubleA = false;
       
   281   m_gotDoubleB = false;
       
   282   traceDoubleA (0);
       
   283   traceDoubleB (0);
       
   284   if (!m_gotDoubleA || m_gotDoubleB)
       
   285     {
       
   286       ok = false;
       
   287     }
       
   288   resolver.Disconnect ("/trace-double-a", 
       
   289 		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   290 
       
   291   resolver.Connect ("/(trace-double-a|trace-double-b)", 
       
   292 		    MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   293   m_gotDoubleA = false;
       
   294   m_gotDoubleB = false;
       
   295   traceDoubleA (0);
       
   296   traceDoubleB (0);
       
   297   if (!m_gotDoubleA || !m_gotDoubleB)
       
   298     {
       
   299       ok = false;
       
   300     }
       
   301   resolver.Disconnect ("/trace-double-a", 
       
   302 		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   303   m_gotDoubleA = false;
       
   304   m_gotDoubleB = false;
       
   305   traceDoubleA (0);
       
   306   traceDoubleB (0);
       
   307   if (m_gotDoubleA || !m_gotDoubleB)
       
   308     {
       
   309       ok = false;
       
   310     }
       
   311 
       
   312 
       
   313   resolver.Disconnect ("/(trace-double-a|trace-double-b)", 
       
   314 		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
       
   315   m_gotDoubleA = false;
       
   316   m_gotDoubleB = false;
       
   317   traceDoubleA (0);
       
   318   traceDoubleB (0);
       
   319   if (m_gotDoubleA || m_gotDoubleB)
       
   320     {
       
   321       ok = false;
       
   322     }
       
   323 
       
   324   resolver.Add ("subresolver", 
       
   325 		MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this),
       
   326 		TraceSourceTest (TraceSourceTest::SUBRESOLVER));
       
   327 
       
   328   resolver.Connect ("/subresolver/trace-int", 
       
   329 		    MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
       
   330   m_gotInt = false;
       
   331   m_traceInt (1);
       
   332   if (!m_gotInt)
       
   333     {
       
   334       ok = false;
       
   335     }
       
   336 
       
   337   resolver.Disconnect ("/subresolver/trace-int", 
       
   338 		       MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
       
   339   m_gotInt = false;
       
   340   m_traceInt (1);
       
   341   if (m_gotInt)
       
   342     {
       
   343       ok = false;
       
   344     }
       
   345 
       
   346   resolver.Connect ("/*/trace-int", 
       
   347 		    MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
       
   348   m_gotInt = false;
       
   349   m_traceInt (1);
       
   350   if (!m_gotInt)
       
   351     {
       
   352       ok = false;
       
   353     }
       
   354 
       
   355   resolver.Disconnect ("/subresolver/trace-int", 
       
   356 		       MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
       
   357   m_gotInt = false;
       
   358   m_traceInt (1);
       
   359   if (m_gotInt)
       
   360     {
       
   361       ok = false;
       
   362     }
       
   363 
       
   364 
       
   365   
       
   366 
       
   367   return ok;
       
   368 }
       
   369 
       
   370 static CompositeTraceResolverTest g_compositeTraceResolverTest;
       
   371 
       
   372 }//namespace ns3
       
   373 
       
   374 
       
   375 #endif /* RUN_SELF_TESTS */