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