NS_LOG parsing changes to address bug 91 ns-3.0.7
authorCraig Dowell <craigdo@ee.washington.edu>
Mon, 15 Oct 2007 14:54:32 -0700
changeset 1783 36472385a1cc
parent 1782 444ef6129d2e
child 1784 5d071f2f2eca
NS_LOG parsing changes to address bug 91
src/core/log.cc
src/core/log.h
--- a/src/core/log.cc	Sat Oct 13 15:14:00 2007 -0700
+++ b/src/core/log.cc	Mon Oct 15 14:54:32 2007 -0700
@@ -18,6 +18,8 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
+// What about print-list!!!!!!???????
+
 #ifdef NS3_LOG_ENABLE
 
 #include <list>
@@ -44,69 +46,33 @@
   return &components;
 }
 
-void
-LogComponentEnableEnvVar (void)
+LogComponent::LogComponent (char const * name)
+  : m_levels (0), m_name (name)
 {
-  static bool isFirstLog = true;
-#if 0
-//
-// Interesting static constructor bug:
-//
-// The RandomDirection2dMobilityModel declares a RandomVariableDefaultValue
-// g_speedVariable.  This variable is initialized in the 
-// static_initialization_and_destruction_0 function as expected.  This causes
-// RandomVariableDefaultValue::Parse () to be called which calls NS_LOG_X
-// functions.  The macro calls LogComponent::IsEnabled () which calls 
-// LogComponentEnableEnvVar ().  The following variable called isFirstLog
-// is set after the first call to prevent the environment variable from
-// actually being parsed on every log call.
-//
-// When the RandomDirection2dMobilityModel static constructor is run, other
-// log components may not have had their static constructors run yet.  It is
-// in those other static constructors that their log components are added to
-// the list of log components.
-//
-// The end result is that if any code calls an NS_LOG_X function during its
-// static constructor, the environment variable check is "locked out" for 
-// any log component declarations (in different compilation units) that have
-// not yet been executed.
-//
-// So, the choice seems to be to either 1) parse the environment variables
-// at every log call; or 2) make LogComponentEnableEnvVar explicitly called
-// after all other static constructors are called.  This means in main ().
-// The former choice seems the only reasonable way out if we care remotely
-// about performance in logging.
-//
-// I made LogComponentEnableEnvVar a public API that you need to call in 
-// main () if you want to use environment variables to drive the log output.
-// 
-  if (!isFirstLog)
+  EnvVarCheck (name);
+
+  ComponentList *components = GetComponentList ();
+  for (ComponentListI i = components->begin ();
+       i != components->end ();
+       i++)
     {
-      return;
+      NS_ASSERT (i->first != name);
     }
-#endif // 0
+  components->push_back (std::make_pair (name, this));
+}
 
+void
+LogComponent::EnvVarCheck (char const * name)
+{
 #ifdef HAVE_GETENV
   char *envVar = getenv("NS_LOG");
   if (envVar == 0)
     {
-      isFirstLog = false;
       return;
     }
   std::string env = envVar;
-  if (env == "print-list")
-    {
-      LogComponentPrintList ();
-      isFirstLog = false;
-      return;
-    }
-  if (env == "*")
-    {
-      LogComponentEnableAll (LOG_DEBUG);
-      isFirstLog = false;
-      return;
-    }
-  bool allFound = true;
+  std::string myName = name;
+
   std::string::size_type cur = 0;
   std::string::size_type next = 0;
   while (true)
@@ -128,118 +94,101 @@
         }
       std::string::size_type equal = tmp.find ("=");
       std::string component;
-      int level = 0;
       if (equal == std::string::npos)
         {
           component = tmp;
-          level = LOG_DEBUG;
+          if (component == myName || component == "*")
+            {
+              Enable (LOG_DEBUG);
+              return;
+            }
         }
       else
         {
           component = tmp.substr (0, equal);
-          std::string::size_type cur_lev;
-          std::string::size_type next_lev = equal;
-          do
+          if (component == myName || component == "*")
             {
-              cur_lev = next_lev + 1;
-              next_lev = tmp.find ("|", cur_lev);
-              std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
-              if (lev == "error")
-                {
-                  level |= LOG_ERROR;
-                }
-              else if (lev == "warn")
-                {
-                  level |= LOG_WARN;
-                }
-              else if (lev == "debug")
-                {
-                  level |= LOG_DEBUG;
-                }
-              else if (lev == "info")
-                {
-                  level |= LOG_INFO;
-                }
-              else if (lev == "function")
-                {
-                  level |= LOG_FUNCTION;
-                }
-              else if (lev == "param")
-                {
-                  level |= LOG_PARAM;
-                }
-              else if (lev == "logic")
-                {
-                  level |= LOG_LOGIC;
-                }
-              else if (lev == "all")
-                {
-                  level |= LOG_ALL;
-                }
-              else if (lev == "prefix")
-                {
-                  level |= LOG_PREFIX_ALL;
-                }
-              else if (lev == "level_error")
-                {
-                  level |= LOG_LEVEL_ERROR;
-                }
-              else if (lev == "level_warn")
+              int level = 0;
+              std::string::size_type cur_lev;
+              std::string::size_type next_lev = equal;
+              do
                 {
-                  level |= LOG_LEVEL_WARN;
-                }
-              else if (lev == "level_debug")
-                {
-                  level |= LOG_LEVEL_DEBUG;
-                }
-              else if (lev == "level_info")
-                {
-                  level |= LOG_LEVEL_INFO;
-                }
-              else if (lev == "level_function")
-                {
-                  level |= LOG_LEVEL_FUNCTION;
-                }
-              else if (lev == "level_param")
-                {
-                  level |= LOG_LEVEL_PARAM;
-                }
-              else if (lev == "level_logic")
-                {
-                  level |= LOG_LEVEL_LOGIC;
-                }
-              else if (lev == "level_all")
-                {
-                  level |= LOG_LEVEL_ALL;
-                }
-            } while (next_lev != std::string::npos);
-        }
-      bool found = false;
-      if (component == "*")
-        {
-          found = true;
-          LogComponentEnableAll ((enum LogLevel)level);
-        }
-      else
-        {
-          ComponentList *components = GetComponentList ();
-          for (ComponentListI i = components->begin ();
-               i != components->end ();
-               i++)
-            {
-              if (i->first.compare (component) == 0)
-                {
-                  found = true;
-                  
-                  i->second->Enable ((enum LogLevel)level);
-                  break;
-                }
+                  cur_lev = next_lev + 1;
+                  next_lev = tmp.find ("|", cur_lev);
+                  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
+                  if (lev == "error")
+                    {
+                      level |= LOG_ERROR;
+                    }
+                  else if (lev == "warn")
+                    {
+                      level |= LOG_WARN;
+                    }
+                  else if (lev == "debug")
+                    {
+                      level |= LOG_DEBUG;
+                    }
+                  else if (lev == "info")
+                    {
+                      level |= LOG_INFO;
+                    }
+                  else if (lev == "function")
+                    {
+                      level |= LOG_FUNCTION;
+                    }
+                  else if (lev == "param")
+                    {
+                      level |= LOG_PARAM;
+                    }
+                  else if (lev == "logic")
+                    {
+                      level |= LOG_LOGIC;
+                    }
+                  else if (lev == "all")
+                    {
+                      level |= LOG_ALL;
+                    }
+                  else if (lev == "prefix")
+                    {
+                      level |= LOG_PREFIX_ALL;
+                    }
+                  else if (lev == "level_error")
+                    {
+                      level |= LOG_LEVEL_ERROR;
+                    }
+                  else if (lev == "level_warn")
+                    {
+                      level |= LOG_LEVEL_WARN;
+                    }
+                  else if (lev == "level_debug")
+                    {
+                      level |= LOG_LEVEL_DEBUG;
+                    }
+                  else if (lev == "level_info")
+                    {
+                      level |= LOG_LEVEL_INFO;
+                    }
+                  else if (lev == "level_function")
+                    {
+                      level |= LOG_LEVEL_FUNCTION;
+                    }
+                  else if (lev == "level_param")
+                    {
+                      level |= LOG_LEVEL_PARAM;
+                    }
+                  else if (lev == "level_logic")
+                    {
+                      level |= LOG_LEVEL_LOGIC;
+                    }
+                  else if (lev == "level_all")
+                    {
+                      level |= LOG_LEVEL_ALL;
+                    }
+                } while (next_lev != std::string::npos);
+
+              Enable ((enum LogLevel)level);
             }
         }
-      if (!found)
-        {
-          allFound = false;
-        }
       if (next == std::string::npos)
         {
           break;
@@ -250,26 +199,9 @@
           break;
         }
     }
-  if (allFound)
-    {
-      isFirstLog = false;
-    }
-  
 #endif
 }
 
-LogComponent::LogComponent (char const * name)
-  : m_levels (0), m_name (name)
-{
-  ComponentList *components = GetComponentList ();
-  for (ComponentListI i = components->begin ();
-       i != components->end ();
-       i++)
-    {
-      NS_ASSERT (i->first != name);
-    }
-  components->push_back (std::make_pair (name, this));
-}
 
 bool 
 LogComponent::IsEnabled (enum LogLevel level) const
--- a/src/core/log.h	Sat Oct 13 15:14:00 2007 -0700
+++ b/src/core/log.h	Mon Oct 15 14:54:32 2007 -0700
@@ -34,6 +34,21 @@
  *     messages, use the ns3::LogComponentEnable
  *     function or use the NS_LOG environment variable and 
  *     ns3::LogComponentEnableEnvVar
+ *
+ * Use the environment variable NS_LOG to define a ';'-separated list of
+ * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
+ * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
+ * NS_LOG=* will enable all available log components.
+ *
+ * For each component, the "debug" log level is enabled by default
+ * but more components can be enabled selectively with the following
+ * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
+ * This example would enable the 'func', 'param', and 'warn' log
+ * levels for 'Component1' and the 'error' and 'debug' log levels
+ * for 'Component2'.  The wildcard can be used here as well.  For example
+ * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
+ * prints with the component and function names.
+ *
  */
 
 /**
@@ -94,7 +109,7 @@
       if (g_log.IsEnabled (level))                              \
         {                                                       \
           std::clog << g_log.Name () << ":" << __FUNCTION__ <<  \
-            "(): " << std::endl;                                \
+            "()" << std::endl;                                \
         }                                                       \
     }                                                           \
   while (false)
@@ -180,28 +195,6 @@
 
 #ifdef NS3_LOG_ENABLE
 /**
- * \brief Enable the logging output based on an environment variable.
- *
- * Use the environment variable NS_LOG to define a ';'-separated list of
- * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
- * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
- * NS_LOG=* will enable all available log components.
- *
- * For each component, the "debug" log level is enabled by default
- * but more components can be enabled selectively with the following
- * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
- * This example would enable the 'func', 'param', and 'warn' log
- * levels for 'Component1' and the 'error' and 'debug' log levels
- * for 'Component2'.  The wildcard can be used here as well.  For example
- * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
- * prints with the component and function names.
- *
- * The list of available log components can be printed on stdout
- * with the NS_LOG=print-list syntax.
- */
-  void LogComponentEnableEnvVar (void);
-
-/**
  * \param name a log component name
  * \param level a logging level
  * \param decorate whether or not to add function names to all logs
@@ -222,7 +215,6 @@
  */
   void LogComponentEnableAll (enum LogLevel level);
 #else
-#define LogComponentEnableEnvVar()
 #define LogComponentEnable(a,b)
 #define LogComponentEnableAll(a)
 #endif
@@ -259,11 +251,6 @@
  * \ingroup logging
  *
  * Print the list of logging messages available.
- * The output of this function can be obtained by setting
- * the NS_LOG environment variable to the special value 
- * 'print-list'.
- * 
- * For example: NS_LOG=print-list
  */
 #ifdef NS3_LOG_ENABLE
 void LogComponentPrintList (void);
@@ -276,6 +263,7 @@
 class LogComponent {
 public:
   LogComponent (char const *name);
+  void EnvVarCheck (char const *name);
   bool IsEnabled (enum LogLevel level) const;
   bool IsNoneEnabled (void) const;
   void Enable (enum LogLevel level);