A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
log.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006,2007 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "log.h"
21 
22 #include <list>
23 #include <utility>
24 #include <iostream>
25 #include <string.h>
26 #include "assert.h"
27 #include "ns3/core-config.h"
28 #include "fatal-error.h"
29 
30 #ifdef HAVE_GETENV
31 #include <string.h>
32 #endif
33 
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 
38 namespace ns3 {
39 
42 
43 typedef std::list<std::pair <std::string, LogComponent *> > ComponentList;
44 typedef std::list<std::pair <std::string, LogComponent *> >::iterator ComponentListI;
45 
46 static class PrintList
47 {
48 public:
49  PrintList ();
50 } g_printList;
51 
52 static
54 {
55  static ComponentList components;
56  return &components;
57 }
58 
59 
60 
62 {
63 #ifdef HAVE_GETENV
64  char *envVar = getenv ("NS_LOG");
65  if (envVar == 0)
66  {
67  return;
68  }
69  std::string env = envVar;
70  std::string::size_type cur = 0;
71  std::string::size_type next = 0;
72  while (next != std::string::npos)
73  {
74  next = env.find_first_of (":", cur);
75  std::string tmp = std::string (env, cur, next-cur);
76  if (tmp == "print-list")
77  {
79  exit (0);
80  break;
81  }
82  cur = next + 1;
83  }
84 #endif
85 }
86 
87 
88 LogComponent::LogComponent (char const * name)
89  : m_levels (0), m_name (name)
90 {
91  EnvVarCheck (name);
92 
93  ComponentList *components = GetComponentList ();
94  for (ComponentListI i = components->begin ();
95  i != components->end ();
96  i++)
97  {
98  if (i->first == name)
99  {
100  NS_FATAL_ERROR ("Log component \""<<name<<"\" has already been registered once.");
101  }
102  }
103  components->push_back (std::make_pair (name, this));
104 }
105 
106 void
107 LogComponent::EnvVarCheck (char const * name)
108 {
109 #ifdef HAVE_GETENV
110  char *envVar = getenv ("NS_LOG");
111  if (envVar == 0)
112  {
113  return;
114  }
115  std::string env = envVar;
116  std::string myName = name;
117 
118  std::string::size_type cur = 0;
119  std::string::size_type next = 0;
120  while (next != std::string::npos)
121  {
122  next = env.find_first_of (":", cur);
123  std::string tmp = std::string (env, cur, next-cur);
124  std::string::size_type equal = tmp.find ("=");
125  std::string component;
126  if (equal == std::string::npos)
127  {
128  component = tmp;
129  if (component == myName || component == "*")
130  {
132  Enable ((enum LogLevel)level);
133  return;
134  }
135  }
136  else
137  {
138  component = tmp.substr (0, equal);
139  if (component == myName || component == "*")
140  {
141  int level = 0;
142  std::string::size_type cur_lev;
143  std::string::size_type next_lev = equal;
144  do
145  {
146  cur_lev = next_lev + 1;
147  next_lev = tmp.find ("|", cur_lev);
148  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
149  if (lev == "error")
150  {
151  level |= LOG_ERROR;
152  }
153  else if (lev == "warn")
154  {
155  level |= LOG_WARN;
156  }
157  else if (lev == "debug")
158  {
159  level |= LOG_DEBUG;
160  }
161  else if (lev == "info")
162  {
163  level |= LOG_INFO;
164  }
165  else if (lev == "function")
166  {
167  level |= LOG_FUNCTION;
168  }
169  else if (lev == "logic")
170  {
171  level |= LOG_LOGIC;
172  }
173  else if (lev == "all")
174  {
175  level |= LOG_ALL;
176  }
177  else if (lev == "prefix_func")
178  {
179  level |= LOG_PREFIX_FUNC;
180  }
181  else if (lev == "prefix_time")
182  {
183  level |= LOG_PREFIX_TIME;
184  }
185  else if (lev == "prefix_node")
186  {
187  level |= LOG_PREFIX_NODE;
188  }
189  else if (lev == "level_error")
190  {
191  level |= LOG_LEVEL_ERROR;
192  }
193  else if (lev == "level_warn")
194  {
195  level |= LOG_LEVEL_WARN;
196  }
197  else if (lev == "level_debug")
198  {
199  level |= LOG_LEVEL_DEBUG;
200  }
201  else if (lev == "level_info")
202  {
203  level |= LOG_LEVEL_INFO;
204  }
205  else if (lev == "level_function")
206  {
207  level |= LOG_LEVEL_FUNCTION;
208  }
209  else if (lev == "level_logic")
210  {
211  level |= LOG_LEVEL_LOGIC;
212  }
213  else if (lev == "level_all")
214  {
215  level |= LOG_LEVEL_ALL;
216  }
217  } while (next_lev != std::string::npos);
218 
219  Enable ((enum LogLevel)level);
220  }
221  }
222  cur = next + 1;
223  }
224 #endif
225 }
226 
227 
228 bool
230 {
231  // LogComponentEnableEnvVar ();
232  return (level & m_levels) ? 1 : 0;
233 }
234 
235 bool
237 {
238  return m_levels == 0;
239 }
240 
241 void
243 {
244  m_levels |= level;
245 }
246 
247 void
249 {
250  m_levels &= ~level;
251 }
252 
253 char const *
254 LogComponent::Name (void) const
255 {
256  return m_name;
257 }
258 
259 
260 void
261 LogComponentEnable (char const *name, enum LogLevel level)
262 {
263  ComponentList *components = GetComponentList ();
264  ComponentListI i;
265  for (i = components->begin ();
266  i != components->end ();
267  i++)
268  {
269  if (i->first.compare (name) == 0)
270  {
271  i->second->Enable (level);
272  return;
273  }
274  }
275  if (i == components->end())
276  {
277  // nothing matched
279  NS_FATAL_ERROR ("Logging component \"" << name <<
280  "\" not found. See above for a list of available log components");
281  }
282 }
283 
284 void
286 {
287  ComponentList *components = GetComponentList ();
288  for (ComponentListI i = components->begin ();
289  i != components->end ();
290  i++)
291  {
292  i->second->Enable (level);
293  }
294 }
295 
296 void
297 LogComponentDisable (char const *name, enum LogLevel level)
298 {
299  ComponentList *components = GetComponentList ();
300  for (ComponentListI i = components->begin ();
301  i != components->end ();
302  i++)
303  {
304  if (i->first.compare (name) == 0)
305  {
306  i->second->Disable (level);
307  break;
308  }
309  }
310 }
311 
312 void
314 {
315  ComponentList *components = GetComponentList ();
316  for (ComponentListI i = components->begin ();
317  i != components->end ();
318  i++)
319  {
320  i->second->Disable (level);
321  }
322 }
323 
324 void
326 {
327  ComponentList *components = GetComponentList ();
328  for (ComponentListI i = components->begin ();
329  i != components->end ();
330  i++)
331  {
332  std::cout << i->first << "=";
333  if (i->second->IsNoneEnabled ())
334  {
335  std::cout << "0" << std::endl;
336  continue;
337  }
338  if (i->second->IsEnabled (LOG_ERROR))
339  {
340  std::cout << "error";
341  }
342  if (i->second->IsEnabled (LOG_WARN))
343  {
344  std::cout << "|warn";
345  }
346  if (i->second->IsEnabled (LOG_DEBUG))
347  {
348  std::cout << "|debug";
349  }
350  if (i->second->IsEnabled (LOG_INFO))
351  {
352  std::cout << "|info";
353  }
354  if (i->second->IsEnabled (LOG_FUNCTION))
355  {
356  std::cout << "|function";
357  }
358  if (i->second->IsEnabled (LOG_LOGIC))
359  {
360  std::cout << "|logic";
361  }
362  if (i->second->IsEnabled (LOG_ALL))
363  {
364  std::cout << "|all";
365  }
366  std::cout << std::endl;
367  }
368 }
369 
370 static bool ComponentExists(std::string componentName)
371 {
372  char const*name=componentName.c_str();
373  ComponentList *components = GetComponentList ();
374  ComponentListI i;
375  for (i = components->begin ();
376  i != components->end ();
377  i++)
378  {
379  if (i->first.compare (name) == 0)
380  {
381  return true;
382  }
383  }
384  NS_ASSERT (i == components->end());
385  // nothing matched
386  return false;
387 }
388 
389 static void CheckEnvironmentVariables (void)
390 {
391 #ifdef HAVE_GETENV
392  char *envVar = getenv ("NS_LOG");
393  if (envVar == 0 || strlen(envVar) == 0)
394  {
395  return;
396  }
397  std::string env = envVar;
398 
399  std::string::size_type cur = 0;
400  std::string::size_type next = 0;
401 
402  while (next != std::string::npos)
403  {
404  next = env.find_first_of (":", cur);
405  std::string tmp = std::string (env, cur, next-cur);
406  std::string::size_type equal = tmp.find ("=");
407  std::string component;
408  if (equal == std::string::npos)
409  {
410  // ie no '=' characters found
411  component = tmp;
412  if (ComponentExists(component) || component == "*")
413  {
414  return;
415  }
416  else
417  {
419  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
420  "\" in env variable NS_LOG, see above for a list of valid components");
421  }
422  }
423  else
424  {
425  component = tmp.substr (0, equal);
426  if (ComponentExists(component) || component == "*")
427  {
428  std::string::size_type cur_lev;
429  std::string::size_type next_lev = equal;
430  do
431  {
432  cur_lev = next_lev + 1;
433  next_lev = tmp.find ("|", cur_lev);
434  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
435  if (lev == "error"
436  || lev == "warn"
437  || lev == "debug"
438  || lev == "info"
439  || lev == "function"
440  || lev == "logic"
441  || lev == "all"
442  || lev == "prefix_func"
443  || lev == "prefix_time"
444  || lev == "prefix_node"
445  || lev == "level_error"
446  || lev == "level_warn"
447  || lev == "level_debug"
448  || lev == "level_info"
449  || lev == "level_function"
450  || lev == "level_logic"
451  || lev == "level_all"
452  || lev == "*"
453  )
454  {
455  continue;
456  }
457  else
458  {
459  NS_FATAL_ERROR("Invalid log level \"" << lev <<
460  "\" in env variable NS_LOG for component name " << component);
461  }
462  } while (next_lev != std::string::npos);
463  }
464  else
465  {
467  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
468  "\" in env variable NS_LOG, see above for a list of valid components");
469  }
470  }
471  cur = next + 1; // parse next component
472  }
473 #endif
474 }
476 {
477  g_logTimePrinter = printer;
478  // This is the only place where we are more or less sure that all log variables
479  // are registered. See bug 1082 for details.
481 }
483 {
484  return g_logTimePrinter;
485 }
486 
488 {
489  g_logNodePrinter = printer;
490 }
492 {
493  return g_logNodePrinter;
494 }
495 
496 
498  : m_itemNumber (0),
499  m_os (os)
500 {
501 }
502 
503 } // namespace ns3