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 178336472385a1cc
parent 1782 444ef6129d2e
child 1784 5d071f2f2eca
NS_LOG parsing changes to address bug 91
src/core/log.cc
src/core/log.h
     1.1 --- a/src/core/log.cc	Sat Oct 13 15:14:00 2007 -0700
     1.2 +++ b/src/core/log.cc	Mon Oct 15 14:54:32 2007 -0700
     1.3 @@ -18,6 +18,8 @@
     1.4   * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
     1.5   */
     1.6  
     1.7 +// What about print-list!!!!!!???????
     1.8 +
     1.9  #ifdef NS3_LOG_ENABLE
    1.10  
    1.11  #include <list>
    1.12 @@ -44,69 +46,33 @@
    1.13    return &components;
    1.14  }
    1.15  
    1.16 +LogComponent::LogComponent (char const * name)
    1.17 +  : m_levels (0), m_name (name)
    1.18 +{
    1.19 +  EnvVarCheck (name);
    1.20 +
    1.21 +  ComponentList *components = GetComponentList ();
    1.22 +  for (ComponentListI i = components->begin ();
    1.23 +       i != components->end ();
    1.24 +       i++)
    1.25 +    {
    1.26 +      NS_ASSERT (i->first != name);
    1.27 +    }
    1.28 +  components->push_back (std::make_pair (name, this));
    1.29 +}
    1.30 +
    1.31  void
    1.32 -LogComponentEnableEnvVar (void)
    1.33 +LogComponent::EnvVarCheck (char const * name)
    1.34  {
    1.35 -  static bool isFirstLog = true;
    1.36 -#if 0
    1.37 -//
    1.38 -// Interesting static constructor bug:
    1.39 -//
    1.40 -// The RandomDirection2dMobilityModel declares a RandomVariableDefaultValue
    1.41 -// g_speedVariable.  This variable is initialized in the 
    1.42 -// static_initialization_and_destruction_0 function as expected.  This causes
    1.43 -// RandomVariableDefaultValue::Parse () to be called which calls NS_LOG_X
    1.44 -// functions.  The macro calls LogComponent::IsEnabled () which calls 
    1.45 -// LogComponentEnableEnvVar ().  The following variable called isFirstLog
    1.46 -// is set after the first call to prevent the environment variable from
    1.47 -// actually being parsed on every log call.
    1.48 -//
    1.49 -// When the RandomDirection2dMobilityModel static constructor is run, other
    1.50 -// log components may not have had their static constructors run yet.  It is
    1.51 -// in those other static constructors that their log components are added to
    1.52 -// the list of log components.
    1.53 -//
    1.54 -// The end result is that if any code calls an NS_LOG_X function during its
    1.55 -// static constructor, the environment variable check is "locked out" for 
    1.56 -// any log component declarations (in different compilation units) that have
    1.57 -// not yet been executed.
    1.58 -//
    1.59 -// So, the choice seems to be to either 1) parse the environment variables
    1.60 -// at every log call; or 2) make LogComponentEnableEnvVar explicitly called
    1.61 -// after all other static constructors are called.  This means in main ().
    1.62 -// The former choice seems the only reasonable way out if we care remotely
    1.63 -// about performance in logging.
    1.64 -//
    1.65 -// I made LogComponentEnableEnvVar a public API that you need to call in 
    1.66 -// main () if you want to use environment variables to drive the log output.
    1.67 -// 
    1.68 -  if (!isFirstLog)
    1.69 -    {
    1.70 -      return;
    1.71 -    }
    1.72 -#endif // 0
    1.73 -
    1.74  #ifdef HAVE_GETENV
    1.75    char *envVar = getenv("NS_LOG");
    1.76    if (envVar == 0)
    1.77      {
    1.78 -      isFirstLog = false;
    1.79        return;
    1.80      }
    1.81    std::string env = envVar;
    1.82 -  if (env == "print-list")
    1.83 -    {
    1.84 -      LogComponentPrintList ();
    1.85 -      isFirstLog = false;
    1.86 -      return;
    1.87 -    }
    1.88 -  if (env == "*")
    1.89 -    {
    1.90 -      LogComponentEnableAll (LOG_DEBUG);
    1.91 -      isFirstLog = false;
    1.92 -      return;
    1.93 -    }
    1.94 -  bool allFound = true;
    1.95 +  std::string myName = name;
    1.96 +
    1.97    std::string::size_type cur = 0;
    1.98    std::string::size_type next = 0;
    1.99    while (true)
   1.100 @@ -128,118 +94,101 @@
   1.101          }
   1.102        std::string::size_type equal = tmp.find ("=");
   1.103        std::string component;
   1.104 -      int level = 0;
   1.105        if (equal == std::string::npos)
   1.106          {
   1.107            component = tmp;
   1.108 -          level = LOG_DEBUG;
   1.109 +          if (component == myName || component == "*")
   1.110 +            {
   1.111 +              Enable (LOG_DEBUG);
   1.112 +              return;
   1.113 +            }
   1.114          }
   1.115        else
   1.116          {
   1.117            component = tmp.substr (0, equal);
   1.118 -          std::string::size_type cur_lev;
   1.119 -          std::string::size_type next_lev = equal;
   1.120 -          do
   1.121 +          if (component == myName || component == "*")
   1.122              {
   1.123 -              cur_lev = next_lev + 1;
   1.124 -              next_lev = tmp.find ("|", cur_lev);
   1.125 -              std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
   1.126 -              if (lev == "error")
   1.127 +              int level = 0;
   1.128 +              std::string::size_type cur_lev;
   1.129 +              std::string::size_type next_lev = equal;
   1.130 +              do
   1.131                  {
   1.132 -                  level |= LOG_ERROR;
   1.133 -                }
   1.134 -              else if (lev == "warn")
   1.135 -                {
   1.136 -                  level |= LOG_WARN;
   1.137 -                }
   1.138 -              else if (lev == "debug")
   1.139 -                {
   1.140 -                  level |= LOG_DEBUG;
   1.141 -                }
   1.142 -              else if (lev == "info")
   1.143 -                {
   1.144 -                  level |= LOG_INFO;
   1.145 -                }
   1.146 -              else if (lev == "function")
   1.147 -                {
   1.148 -                  level |= LOG_FUNCTION;
   1.149 -                }
   1.150 -              else if (lev == "param")
   1.151 -                {
   1.152 -                  level |= LOG_PARAM;
   1.153 -                }
   1.154 -              else if (lev == "logic")
   1.155 -                {
   1.156 -                  level |= LOG_LOGIC;
   1.157 -                }
   1.158 -              else if (lev == "all")
   1.159 -                {
   1.160 -                  level |= LOG_ALL;
   1.161 -                }
   1.162 -              else if (lev == "prefix")
   1.163 -                {
   1.164 -                  level |= LOG_PREFIX_ALL;
   1.165 -                }
   1.166 -              else if (lev == "level_error")
   1.167 -                {
   1.168 -                  level |= LOG_LEVEL_ERROR;
   1.169 -                }
   1.170 -              else if (lev == "level_warn")
   1.171 -                {
   1.172 -                  level |= LOG_LEVEL_WARN;
   1.173 -                }
   1.174 -              else if (lev == "level_debug")
   1.175 -                {
   1.176 -                  level |= LOG_LEVEL_DEBUG;
   1.177 -                }
   1.178 -              else if (lev == "level_info")
   1.179 -                {
   1.180 -                  level |= LOG_LEVEL_INFO;
   1.181 -                }
   1.182 -              else if (lev == "level_function")
   1.183 -                {
   1.184 -                  level |= LOG_LEVEL_FUNCTION;
   1.185 -                }
   1.186 -              else if (lev == "level_param")
   1.187 -                {
   1.188 -                  level |= LOG_LEVEL_PARAM;
   1.189 -                }
   1.190 -              else if (lev == "level_logic")
   1.191 -                {
   1.192 -                  level |= LOG_LEVEL_LOGIC;
   1.193 -                }
   1.194 -              else if (lev == "level_all")
   1.195 -                {
   1.196 -                  level |= LOG_LEVEL_ALL;
   1.197 -                }
   1.198 -            } while (next_lev != std::string::npos);
   1.199 -        }
   1.200 -      bool found = false;
   1.201 -      if (component == "*")
   1.202 -        {
   1.203 -          found = true;
   1.204 -          LogComponentEnableAll ((enum LogLevel)level);
   1.205 -        }
   1.206 -      else
   1.207 -        {
   1.208 -          ComponentList *components = GetComponentList ();
   1.209 -          for (ComponentListI i = components->begin ();
   1.210 -               i != components->end ();
   1.211 -               i++)
   1.212 -            {
   1.213 -              if (i->first.compare (component) == 0)
   1.214 -                {
   1.215 -                  found = true;
   1.216 -                  
   1.217 -                  i->second->Enable ((enum LogLevel)level);
   1.218 -                  break;
   1.219 -                }
   1.220 +                  cur_lev = next_lev + 1;
   1.221 +                  next_lev = tmp.find ("|", cur_lev);
   1.222 +                  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
   1.223 +                  if (lev == "error")
   1.224 +                    {
   1.225 +                      level |= LOG_ERROR;
   1.226 +                    }
   1.227 +                  else if (lev == "warn")
   1.228 +                    {
   1.229 +                      level |= LOG_WARN;
   1.230 +                    }
   1.231 +                  else if (lev == "debug")
   1.232 +                    {
   1.233 +                      level |= LOG_DEBUG;
   1.234 +                    }
   1.235 +                  else if (lev == "info")
   1.236 +                    {
   1.237 +                      level |= LOG_INFO;
   1.238 +                    }
   1.239 +                  else if (lev == "function")
   1.240 +                    {
   1.241 +                      level |= LOG_FUNCTION;
   1.242 +                    }
   1.243 +                  else if (lev == "param")
   1.244 +                    {
   1.245 +                      level |= LOG_PARAM;
   1.246 +                    }
   1.247 +                  else if (lev == "logic")
   1.248 +                    {
   1.249 +                      level |= LOG_LOGIC;
   1.250 +                    }
   1.251 +                  else if (lev == "all")
   1.252 +                    {
   1.253 +                      level |= LOG_ALL;
   1.254 +                    }
   1.255 +                  else if (lev == "prefix")
   1.256 +                    {
   1.257 +                      level |= LOG_PREFIX_ALL;
   1.258 +                    }
   1.259 +                  else if (lev == "level_error")
   1.260 +                    {
   1.261 +                      level |= LOG_LEVEL_ERROR;
   1.262 +                    }
   1.263 +                  else if (lev == "level_warn")
   1.264 +                    {
   1.265 +                      level |= LOG_LEVEL_WARN;
   1.266 +                    }
   1.267 +                  else if (lev == "level_debug")
   1.268 +                    {
   1.269 +                      level |= LOG_LEVEL_DEBUG;
   1.270 +                    }
   1.271 +                  else if (lev == "level_info")
   1.272 +                    {
   1.273 +                      level |= LOG_LEVEL_INFO;
   1.274 +                    }
   1.275 +                  else if (lev == "level_function")
   1.276 +                    {
   1.277 +                      level |= LOG_LEVEL_FUNCTION;
   1.278 +                    }
   1.279 +                  else if (lev == "level_param")
   1.280 +                    {
   1.281 +                      level |= LOG_LEVEL_PARAM;
   1.282 +                    }
   1.283 +                  else if (lev == "level_logic")
   1.284 +                    {
   1.285 +                      level |= LOG_LEVEL_LOGIC;
   1.286 +                    }
   1.287 +                  else if (lev == "level_all")
   1.288 +                    {
   1.289 +                      level |= LOG_LEVEL_ALL;
   1.290 +                    }
   1.291 +                } while (next_lev != std::string::npos);
   1.292 +
   1.293 +              Enable ((enum LogLevel)level);
   1.294              }
   1.295          }
   1.296 -      if (!found)
   1.297 -        {
   1.298 -          allFound = false;
   1.299 -        }
   1.300        if (next == std::string::npos)
   1.301          {
   1.302            break;
   1.303 @@ -250,26 +199,9 @@
   1.304            break;
   1.305          }
   1.306      }
   1.307 -  if (allFound)
   1.308 -    {
   1.309 -      isFirstLog = false;
   1.310 -    }
   1.311 -  
   1.312  #endif
   1.313  }
   1.314  
   1.315 -LogComponent::LogComponent (char const * name)
   1.316 -  : m_levels (0), m_name (name)
   1.317 -{
   1.318 -  ComponentList *components = GetComponentList ();
   1.319 -  for (ComponentListI i = components->begin ();
   1.320 -       i != components->end ();
   1.321 -       i++)
   1.322 -    {
   1.323 -      NS_ASSERT (i->first != name);
   1.324 -    }
   1.325 -  components->push_back (std::make_pair (name, this));
   1.326 -}
   1.327  
   1.328  bool 
   1.329  LogComponent::IsEnabled (enum LogLevel level) const
     2.1 --- a/src/core/log.h	Sat Oct 13 15:14:00 2007 -0700
     2.2 +++ b/src/core/log.h	Mon Oct 15 14:54:32 2007 -0700
     2.3 @@ -34,6 +34,21 @@
     2.4   *     messages, use the ns3::LogComponentEnable
     2.5   *     function or use the NS_LOG environment variable and 
     2.6   *     ns3::LogComponentEnableEnvVar
     2.7 + *
     2.8 + * Use the environment variable NS_LOG to define a ';'-separated list of
     2.9 + * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
    2.10 + * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
    2.11 + * NS_LOG=* will enable all available log components.
    2.12 + *
    2.13 + * For each component, the "debug" log level is enabled by default
    2.14 + * but more components can be enabled selectively with the following
    2.15 + * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
    2.16 + * This example would enable the 'func', 'param', and 'warn' log
    2.17 + * levels for 'Component1' and the 'error' and 'debug' log levels
    2.18 + * for 'Component2'.  The wildcard can be used here as well.  For example
    2.19 + * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
    2.20 + * prints with the component and function names.
    2.21 + *
    2.22   */
    2.23  
    2.24  /**
    2.25 @@ -94,7 +109,7 @@
    2.26        if (g_log.IsEnabled (level))                              \
    2.27          {                                                       \
    2.28            std::clog << g_log.Name () << ":" << __FUNCTION__ <<  \
    2.29 -            "(): " << std::endl;                                \
    2.30 +            "()" << std::endl;                                \
    2.31          }                                                       \
    2.32      }                                                           \
    2.33    while (false)
    2.34 @@ -180,28 +195,6 @@
    2.35  
    2.36  #ifdef NS3_LOG_ENABLE
    2.37  /**
    2.38 - * \brief Enable the logging output based on an environment variable.
    2.39 - *
    2.40 - * Use the environment variable NS_LOG to define a ';'-separated list of
    2.41 - * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
    2.42 - * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
    2.43 - * NS_LOG=* will enable all available log components.
    2.44 - *
    2.45 - * For each component, the "debug" log level is enabled by default
    2.46 - * but more components can be enabled selectively with the following
    2.47 - * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
    2.48 - * This example would enable the 'func', 'param', and 'warn' log
    2.49 - * levels for 'Component1' and the 'error' and 'debug' log levels
    2.50 - * for 'Component2'.  The wildcard can be used here as well.  For example
    2.51 - * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
    2.52 - * prints with the component and function names.
    2.53 - *
    2.54 - * The list of available log components can be printed on stdout
    2.55 - * with the NS_LOG=print-list syntax.
    2.56 - */
    2.57 -  void LogComponentEnableEnvVar (void);
    2.58 -
    2.59 -/**
    2.60   * \param name a log component name
    2.61   * \param level a logging level
    2.62   * \param decorate whether or not to add function names to all logs
    2.63 @@ -222,7 +215,6 @@
    2.64   */
    2.65    void LogComponentEnableAll (enum LogLevel level);
    2.66  #else
    2.67 -#define LogComponentEnableEnvVar()
    2.68  #define LogComponentEnable(a,b)
    2.69  #define LogComponentEnableAll(a)
    2.70  #endif
    2.71 @@ -259,11 +251,6 @@
    2.72   * \ingroup logging
    2.73   *
    2.74   * Print the list of logging messages available.
    2.75 - * The output of this function can be obtained by setting
    2.76 - * the NS_LOG environment variable to the special value 
    2.77 - * 'print-list'.
    2.78 - * 
    2.79 - * For example: NS_LOG=print-list
    2.80   */
    2.81  #ifdef NS3_LOG_ENABLE
    2.82  void LogComponentPrintList (void);
    2.83 @@ -276,6 +263,7 @@
    2.84  class LogComponent {
    2.85  public:
    2.86    LogComponent (char const *name);
    2.87 +  void EnvVarCheck (char const *name);
    2.88    bool IsEnabled (enum LogLevel level) const;
    2.89    bool IsNoneEnabled (void) const;
    2.90    void Enable (enum LogLevel level);