vlog_is_on.cc
Go to the documentation of this file.
1 // Copyright (c) 1999, 2007, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Ray Sidney and many others
31 //
32 // Broken out from logging.cc by Soren Lassen
33 // logging_unittest.cc covers the functionality herein
34 
35 #include "utilities.h"
36 
37 #include <cstring>
38 #include <cstdlib>
39 #include <cerrno>
40 #include <cstdio>
41 #include <string>
42 #include "base/commandlineflags.h"
43 #include <glog/logging.h>
44 #include <glog/raw_logging.h>
45 #include "base/googleinit.h"
46 
47 // glog doesn't have annotation
48 #define ANNOTATE_BENIGN_RACE(address, description)
49 
50 using std::string;
51 
52 GLOG_DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this."
53 " Overridable by --vmodule.");
54 
55 GLOG_DEFINE_string(vmodule, "", "per-module verbose level."
56 " Argument is a comma-separated list of <module name>=<log level>."
57 " <module name> is a glob pattern, matched against the filename base"
58 " (that is, name ignoring .cc/.h./-inl.h)."
59 " <log level> overrides any value given by --v.");
60 
62 
63 namespace glog_internal_namespace_ {
64 
65 // Used by logging_unittests.cc so can't make it static here.
66 GLOG_EXPORT bool SafeFNMatch_(const char* pattern, size_t patt_len,
67  const char* str, size_t str_len);
68 
69 // Implementation of fnmatch that does not need 0-termination
70 // of arguments and does not allocate any memory,
71 // but we only support "*" and "?" wildcards, not the "[...]" patterns.
72 // It's not a static function for the unittest.
73 GLOG_EXPORT bool SafeFNMatch_(const char* pattern, size_t patt_len,
74  const char* str, size_t str_len) {
75  size_t p = 0;
76  size_t s = 0;
77  while (1) {
78  if (p == patt_len && s == str_len) return true;
79  if (p == patt_len) return false;
80  if (s == str_len) return p+1 == patt_len && pattern[p] == '*';
81  if (pattern[p] == str[s] || pattern[p] == '?') {
82  p += 1;
83  s += 1;
84  continue;
85  }
86  if (pattern[p] == '*') {
87  if (p+1 == patt_len) return true;
88  do {
89  if (SafeFNMatch_(pattern+(p+1), patt_len-(p+1), str+s, str_len-s)) {
90  return true;
91  }
92  s += 1;
93  } while (s != str_len);
94  return false;
95  }
96  return false;
97  }
98 }
99 
100 } // namespace glog_internal_namespace_
101 
103 
104 // List of per-module log levels from FLAGS_vmodule.
105 // Once created each element is never deleted/modified
106 // except for the vlog_level: other threads will read VModuleInfo blobs
107 // w/o locks and we'll store pointers to vlog_level at VLOG locations
108 // that will never go away.
109 // We can't use an STL struct here as we wouldn't know
110 // when it's safe to delete/update it: other threads need to use it w/o locks.
111 struct VModuleInfo {
113  mutable int32 vlog_level; // Conceptually this is an AtomicWord, but it's
114  // too much work to use AtomicWord type here
115  // w/o much actual benefit.
117 };
118 
119 // This protects the following global variables.
121 // Pointer to head of the VModuleInfo list.
122 // It's a map from module pattern to logging level for those module(s).
124 static SiteFlag* cached_site_list = 0;
125 
126 // Boolean initialization flag.
127 static bool inited_vmodule = false;
128 
129 // L >= vmodule_lock.
130 static void VLOG2Initializer() {
132  // Can now parse --vmodule flag and initialize mapping of module-specific
133  // logging levels.
134  inited_vmodule = false;
135  const char* vmodule = FLAGS_vmodule.c_str();
136  const char* sep;
137  VModuleInfo* head = NULL;
138  VModuleInfo* tail = NULL;
139  while ((sep = strchr(vmodule, '=')) != NULL) {
140  string pattern(vmodule, static_cast<size_t>(sep - vmodule));
141  int module_level;
142  if (sscanf(sep, "=%d", &module_level) == 1) {
143  VModuleInfo* info = new VModuleInfo;
144  info->module_pattern = pattern;
145  info->vlog_level = module_level;
146  if (head) {
147  tail->next = info;
148  } else {
149  head = info;
150  }
151  tail = info;
152  }
153  // Skip past this entry
154  vmodule = strchr(sep, ',');
155  if (vmodule == NULL) break;
156  vmodule++; // Skip past ","
157  }
158  if (head) { // Put them into the list at the head:
159  tail->next = vmodule_list;
160  vmodule_list = head;
161  }
162  inited_vmodule = true;
163 }
164 
165 // This can be called very early, so we use SpinLock and RAW_VLOG here.
166 int SetVLOGLevel(const char* module_pattern, int log_level) {
167  int result = FLAGS_v;
168  size_t const pattern_len = strlen(module_pattern);
169  bool found = false;
170  {
171  MutexLock l(&vmodule_lock); // protect whole read-modify-write
172  for (const VModuleInfo* info = vmodule_list;
173  info != NULL; info = info->next) {
174  if (info->module_pattern == module_pattern) {
175  if (!found) {
176  result = info->vlog_level;
177  found = true;
178  }
179  info->vlog_level = log_level;
180  } else if (!found &&
181  SafeFNMatch_(info->module_pattern.c_str(),
182  info->module_pattern.size(),
183  module_pattern, pattern_len)) {
184  result = info->vlog_level;
185  found = true;
186  }
187  }
188  if (!found) {
189  VModuleInfo* info = new VModuleInfo;
190  info->module_pattern = module_pattern;
191  info->vlog_level = log_level;
192  info->next = vmodule_list;
193  vmodule_list = info;
194 
195  SiteFlag** item_ptr = &cached_site_list;
196  SiteFlag* item = cached_site_list;
197 
198  // We traverse the list fully because the pattern can match several items
199  // from the list.
200  while (item) {
201  if (SafeFNMatch_(module_pattern, pattern_len, item->base_name,
202  item->base_len)) {
203  // Redirect the cached value to its module override.
204  item->level = &info->vlog_level;
205  *item_ptr = item->next; // Remove the item from the list.
206  } else {
207  item_ptr = &item->next;
208  }
209  item = *item_ptr;
210  }
211  }
212  }
213  RAW_VLOG(1, "Set VLOG level for \"%s\" to %d", module_pattern, log_level);
214  return result;
215 }
216 
217 // NOTE: Individual VLOG statements cache the integer log level pointers.
218 // NOTE: This function must not allocate memory or require any locks.
219 bool InitVLOG3__(SiteFlag* site_flag, int32* level_default,
220  const char* fname, int32 verbose_level) {
222  bool read_vmodule_flag = inited_vmodule;
223  if (!read_vmodule_flag) {
225  }
226 
227  // protect the errno global in case someone writes:
228  // VLOG(..) << "The last error was " << strerror(errno)
229  int old_errno = errno;
230 
231  // site_default normally points to FLAGS_v
232  int32* site_flag_value = level_default;
233 
234  // Get basename for file
235  const char* base = strrchr(fname, '/');
236 
237 #ifdef _WIN32
238  if (!base) {
239  base = strrchr(fname, '\\');
240  }
241 #endif
242 
243  base = base ? (base+1) : fname;
244  const char* base_end = strchr(base, '.');
245  size_t base_length = base_end ? size_t(base_end - base) : strlen(base);
246 
247  // Trim out trailing "-inl" if any
248  if (base_length >= 4 && (memcmp(base+base_length-4, "-inl", 4) == 0)) {
249  base_length -= 4;
250  }
251 
252  // TODO: Trim out _unittest suffix? Perhaps it is better to have
253  // the extra control and just leave it there.
254 
255  // find target in vector of modules, replace site_flag_value with
256  // a module-specific verbose level, if any.
257  for (const VModuleInfo* info = vmodule_list;
258  info != NULL; info = info->next) {
259  if (SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(),
260  base, base_length)) {
261  site_flag_value = &info->vlog_level;
262  // value at info->vlog_level is now what controls
263  // the VLOG at the caller site forever
264  break;
265  }
266  }
267 
268  // Cache the vlog value pointer if --vmodule flag has been parsed.
269  ANNOTATE_BENIGN_RACE(site_flag,
270  "*site_flag may be written by several threads,"
271  " but the value will be the same");
272  if (read_vmodule_flag) {
273  site_flag->level = site_flag_value;
274  // If VLOG flag has been cached to the default site pointer,
275  // we want to add to the cached list in order to invalidate in case
276  // SetVModule is called afterwards with new modules.
277  // The performance penalty here is neglible, because InitVLOG3__ is called
278  // once per site.
279  if (site_flag_value == level_default && !site_flag->base_name) {
280  site_flag->base_name = base;
281  site_flag->base_len = base_length;
282  site_flag->next = cached_site_list;
283  cached_site_list = site_flag;
284  }
285  }
286 
287  // restore the errno in case something recoverable went wrong during
288  // the initialization of the VLOG mechanism (see above note "protect the..")
289  errno = old_errno;
290  return *site_flag_value >= verbose_level;
291 }
292 
293 _END_GOOGLE_NAMESPACE_
SetVLOGLevel
int SetVLOGLevel(const char *module_pattern, int log_level)
Definition: vlog_is_on.cc:166
VModuleInfo::next
const VModuleInfo * next
Definition: vlog_is_on.cc:116
MUTEX_NAMESPACE::MutexLock
Definition: glog/src/base/mutex.h:288
ANNOTATE_BENIGN_RACE
#define ANNOTATE_BENIGN_RACE(address, description)
Definition: vlog_is_on.cc:48
NULL
NULL
Definition: test_security_zap.cpp:405
InitVLOG3__
bool InitVLOG3__(SiteFlag *site_flag, int32 *level_default, const char *fname, int32 verbose_level)
Definition: vlog_is_on.cc:219
googleinit.h
item
cJSON * item
Definition: cJSON.h:236
base
Definition: logging.cc:2162
s
XmlRpcServer s
glog_internal_namespace_
Definition: logging_custom_prefix_unittest.cc:1003
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
errno
int errno
vmodule_lock
static Mutex vmodule_lock
Definition: vlog_is_on.cc:120
vmodule_list
static VModuleInfo * vmodule_list
Definition: vlog_is_on.cc:123
found
return found
Definition: socket_poller.cpp:456
GLOG_EXPORT
#define GLOG_EXPORT
Definition: glog/src/googletest.h:76
MUTEX_NAMESPACE::Mutex
Definition: glog/src/base/mutex.h:159
google::protobuf::int32
int32_t int32
Definition: protobuf/src/google/protobuf/stubs/port.h:150
MUTEX_NAMESPACE::Mutex::AssertHeld
void AssertHeld()
Definition: glog/src/base/mutex.h:185
cJSON::next
struct cJSON * next
Definition: cJSON.h:107
VLOG2Initializer
static void VLOG2Initializer()
Definition: vlog_is_on.cc:130
update_failure_list.str
str
Definition: update_failure_list.py:41
inited_vmodule
static bool inited_vmodule
Definition: vlog_is_on.cc:127
p
const char * p
Definition: gmock-matchers_test.cc:3863
commandlineflags.h
utilities.h
VModuleInfo::vlog_level
int32 vlog_level
Definition: vlog_is_on.cc:113
glog_internal_namespace_::SafeFNMatch_
bool SafeFNMatch_(const char *pattern, size_t patt_len, const char *str, size_t str_len)
Definition: vlog_is_on.cc:73
_START_GOOGLE_NAMESPACE_
Definition: signalhandler.cc:51
VModuleInfo::module_pattern
string module_pattern
Definition: vlog_is_on.cc:112
v
const GLdouble * v
Definition: glcorearb.h:3106
GLOG_DEFINE_string
GLOG_DEFINE_string(vmodule, "", "per-module verbose level." " Argument is a comma-separated list of <module name>=<log level>." " <module name> is a glob pattern, matched against the filename base" " (that is, name ignoring .cc/.h./-inl.h)." " <log level> overrides any value given by --v.")
cached_site_list
static SiteFlag * cached_site_list
Definition: vlog_is_on.cc:124
GLOG_DEFINE_int32
GLOG_DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this." " Overridable by --vmodule.")
VModuleInfo
Definition: vlog_is_on.cc:111


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:01