Panda3D
notifyCategory.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file notifyCategory.cxx
10  * @author drose
11  * @date 2000-02-29
12  */
13 
14 #include "notifyCategory.h"
15 #include "pnotify.h"
16 #include "configPageManager.h"
17 #include "configVariableString.h"
18 #include "configVariableBool.h"
19 #include "config_prc.h"
20 
21 #ifdef ANDROID
22 #include "androidLogStream.h"
23 #endif
24 
25 #include <time.h> // for strftime().
26 #include <assert.h>
27 
28 long NotifyCategory::_server_delta = 0;
29 
30 /**
31  *
32  */
33 NotifyCategory::
34 NotifyCategory(const std::string &fullname, const std::string &basename,
35  NotifyCategory *parent) :
36  _fullname(fullname),
37  _basename(basename),
38  _parent(parent),
39  _severity(get_config_name(), NS_unspecified,
40  "Default severity of this notify category",
41  ConfigVariable::F_dynamic),
42  _local_modified(initial_invalid_cache())
43 {
44  if (_parent != nullptr) {
45  _parent->_children.push_back(this);
46  }
47 
48  // Only the unnamed top category is allowed not to have a parent.
49  nassertv(_parent != nullptr || _fullname.empty());
50 }
51 
52 /**
53  * Begins a new message to this Category at the indicated severity level. If
54  * the indicated severity level is enabled, this writes a prefixing string to
55  * the Notify::out() stream and returns that. If the severity level is
56  * disabled, this returns Notify::null().
57  */
58 std::ostream &NotifyCategory::
59 out(NotifySeverity severity, bool prefix) const {
60  if (is_on(severity)) {
61 
62 #ifdef ANDROID
63  // Android redirects stdio and stderr to devnull, but does provide its own
64  // logging system. We use a special type of stream that redirects it to
65  // Android's log system.
66  if (prefix) {
67  if (severity == NS_info) {
68  return AndroidLogStream::out(severity) << *this << ": ";
69  } else {
70  return AndroidLogStream::out(severity) << *this << "(" << severity << "): ";
71  }
72  } else {
73  return AndroidLogStream::out(severity);
74  }
75 #else
76 
77  if (prefix) {
78  if (get_notify_timestamp()) {
79  // Format a timestamp to include as a prefix as well.
80  time_t now = time(nullptr) + _server_delta;
81  struct tm atm;
82 #ifdef _WIN32
83  localtime_s(&atm, &now);
84 #else
85  localtime_r(&now, &atm);
86 #endif
87 
88  char buffer[128];
89  strftime(buffer, 128, ":%m-%d-%Y %H:%M:%S ", &atm);
90  nout << buffer;
91  }
92 
93  if (severity == NS_info) {
94  return nout << *this << ": ";
95  } else {
96  return nout << *this << "(" << severity << "): ";
97  }
98  } else {
99  return nout;
100  }
101 #endif
102 
103  } else if (severity <= NS_debug && get_check_debug_notify_protect()) {
104  // Someone issued a debug Notify output statement without protecting it
105  // within an if statement. This can cause a significant runtime
106  // performance hit, since it forces the iostream library to fully format
107  // its output, and then discards the output.
108  nout << " **Not protected!** ";
109  if (prefix) {
110  nout << *this << "(" << severity << "): ";
111  }
112  if (assert_abort) {
113  nassert_raise("unprotected debug statement");
114  }
115 
116  return nout;
117 
118  } else {
119  return Notify::null();
120  }
121 }
122 
123 /**
124  * Returns the number of child Categories of this particular Category.
125  */
126 size_t NotifyCategory::
127 get_num_children() const {
128  return _children.size();
129 }
130 
131 /**
132  * Returns the nth child Category of this particular Category.
133  */
135 get_child(size_t i) const {
136  assert(i < _children.size());
137  return _children[i];
138 }
139 
140 /**
141  * Sets a global delta (in seconds) between the local time and the server's
142  * time, for the purpose of synchronizing the time stamps in the log messages
143  * of the client with that of a known server.
144  */
146 set_server_delta(long delta) {
147  _server_delta = delta;
148 }
149 
150 /**
151  * Returns the name of the config variable that controls this category. This
152  * is called at construction time.
153  */
154 std::string NotifyCategory::
155 get_config_name() const {
156  std::string config_name;
157 
158  if (_fullname.empty()) {
159  config_name = "notify-level";
160  } else if (!_basename.empty()) {
161  config_name = "notify-level-" + _basename;
162  }
163 
164  return config_name;
165 }
166 
167 /**
168  *
169  */
170 void NotifyCategory::
171 update_severity_cache() {
172  if (_severity == NS_unspecified) {
173  // If we don't have an explicit severity level, inherit our parent's.
174  if (_severity.has_value()) {
175  nout << "Invalid severity name for " << _severity.get_name() << ": "
176  << _severity.get_string_value() << "\n";
177  }
178  if (_parent != nullptr) {
179  _severity_cache = _parent->get_severity();
180 
181  } else {
182  // Unless, of course, we're the root.
183  _severity_cache = NS_info;
184 
185  // Take this opportunity to have Notify check whether the notify-output
186  // variable changed.
188  }
189  } else {
190  _severity_cache = _severity;
192  }
193 
194  mark_cache_valid(_local_modified);
195 }
196 
197 /**
198  * Returns the value of the notify-timestamp ConfigVariable. This is defined
199  * using a method accessor rather than a static ConfigVariableBool, to protect
200  * against the variable needing to be accessed at static init time.
201  */
202 bool NotifyCategory::
203 get_notify_timestamp() {
204  static ConfigVariableBool *notify_timestamp = nullptr;
205  if (notify_timestamp == nullptr) {
206  notify_timestamp = new ConfigVariableBool
207  ("notify-timestamp", false,
208  "Set true to output the date & time with each notify message.");
209  }
210  return *notify_timestamp;
211 }
212 
213 /**
214  * Returns the value of the check-debug-notify-protect ConfigVariable. This
215  * is defined using a method accessor rather than a static ConfigVariableBool,
216  * to protect against the variable needing to be accessed at static init time.
217  */
218 bool NotifyCategory::
219 get_check_debug_notify_protect() {
220  static ConfigVariableBool *check_debug_notify_protect = nullptr;
221  if (check_debug_notify_protect == nullptr) {
222  check_debug_notify_protect = new ConfigVariableBool
223  ("check-debug-notify-protect", false,
224  "Set true to issue a warning message if a debug or spam "
225  "notify output is not protected within an if statement.");
226  }
227  return *check_debug_notify_protect;
228 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_name
Returns the name of the variable.
bool has_value() const
Returns true if this variable has an explicit value, either from a prc file or locally set,...
This is a convenience class to specialize ConfigVariable as a boolean type.
This is a generic, untyped ConfigVariable.
const std::string & get_string_value() const
Returns the toplevel value of the variable, formatted as a string.
A particular category of error messages.
bool is_on(NotifySeverity severity) const
Returns true if messages of the indicated severity level ought to be reported for this Category.
get_child
Returns the nth child Category of this particular Category.
std::ostream & out(NotifySeverity severity, bool prefix=true) const
Begins a new message to this Category at the indicated severity level.
get_num_children
Returns the number of child Categories of this particular Category.
static void set_server_delta(long delta)
Sets a global delta (in seconds) between the local time and the server's time, for the purpose of syn...
void config_initialized()
Intended to be called only by Config, this is a callback that indicates to Notify when Config has don...
Definition: notify.cxx:428
static std::ostream & null()
A convenient way to get an ostream that doesn't do anything.
Definition: notify.cxx:274
static Notify * ptr()
Returns the pointer to the global Notify object.
Definition: notify.cxx:293
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.