1 // Copyright (c) 1999, 2007, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
30 // Author: Ray Sidney and many others
32 // Broken out from logging.cc by Soren Lassen
33 // logging_unittest.cc covers the functionality herein
35 #include "utilities.h"
42 #include "base/commandlineflags.h"
43 #include "glog/logging.h"
44 #include "glog/raw_logging.h"
45 #include "base/googleinit.h"
47 // glog doesn't have annotation
48 #define ANNOTATE_BENIGN_RACE(address, description)
52 DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this."
53 " Overridable by --vmodule.");
55 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.");
61 _START_GOOGLE_NAMESPACE_
63 namespace glog_internal_namespace_ {
65 // Implementation of fnmatch that does not need 0-termination
66 // of arguments and does not allocate any memory,
67 // but we only support "*" and "?" wildcards, not the "[...]" patterns.
68 // It's not a static function for the unittest.
69 GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
76 if (p == patt_len && s == str_len) return true;
77 if (p == patt_len) return false;
78 if (s == str_len) return p+1 == patt_len && pattern[p] == '*';
79 if (pattern[p] == str[s] || pattern[p] == '?') {
84 if (pattern[p] == '*') {
85 if (p+1 == patt_len) return true;
87 if (SafeFNMatch_(pattern+(p+1), patt_len-(p+1), str+s, str_len-s)) {
91 } while (s != str_len);
98 } // namespace glog_internal_namespace_
100 using glog_internal_namespace_::SafeFNMatch_;
102 int32 kLogSiteUninitialized = 1000;
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.
112 string module_pattern;
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.
116 const VModuleInfo* next;
119 // This protects the following global variables.
120 static Mutex vmodule_lock;
121 // Pointer to head of the VModuleInfo list.
122 // It's a map from module pattern to logging level for those module(s).
123 static VModuleInfo* vmodule_list = 0;
124 // Boolean initialization flag.
125 static bool inited_vmodule = false;
127 // L >= vmodule_lock.
128 static void VLOG2Initializer() {
129 vmodule_lock.AssertHeld();
130 // Can now parse --vmodule flag and initialize mapping of module-specific
132 inited_vmodule = false;
133 const char* vmodule = FLAGS_vmodule.c_str();
135 VModuleInfo* head = NULL;
136 VModuleInfo* tail = NULL;
137 while ((sep = strchr(vmodule, '=')) != NULL) {
138 string pattern(vmodule, sep - vmodule);
140 if (sscanf(sep, "=%d", &module_level) == 1) {
141 VModuleInfo* info = new VModuleInfo;
142 info->module_pattern = pattern;
143 info->vlog_level = module_level;
144 if (head) tail->next = info;
148 // Skip past this entry
149 vmodule = strchr(sep, ',');
150 if (vmodule == NULL) break;
151 vmodule++; // Skip past ","
153 if (head) { // Put them into the list at the head:
154 tail->next = vmodule_list;
157 inited_vmodule = true;
160 // This can be called very early, so we use SpinLock and RAW_VLOG here.
161 int SetVLOGLevel(const char* module_pattern, int log_level) {
162 int result = FLAGS_v;
163 int const pattern_len = strlen(module_pattern);
165 MutexLock l(&vmodule_lock); // protect whole read-modify-write
166 for (const VModuleInfo* info = vmodule_list;
167 info != NULL; info = info->next) {
168 if (info->module_pattern == module_pattern) {
170 result = info->vlog_level;
173 info->vlog_level = log_level;
175 SafeFNMatch_(info->module_pattern.c_str(),
176 info->module_pattern.size(),
177 module_pattern, pattern_len)) {
178 result = info->vlog_level;
183 VModuleInfo* info = new VModuleInfo;
184 info->module_pattern = module_pattern;
185 info->vlog_level = log_level;
186 info->next = vmodule_list;
189 RAW_VLOG(1, "Set VLOG level for \"%s\" to %d", module_pattern, log_level);
193 // NOTE: Individual VLOG statements cache the integer log level pointers.
194 // NOTE: This function must not allocate memory or require any locks.
195 bool InitVLOG3__(int32** site_flag, int32* site_default,
196 const char* fname, int32 verbose_level) {
197 MutexLock l(&vmodule_lock);
198 bool read_vmodule_flag = inited_vmodule;
199 if (!read_vmodule_flag) {
203 // protect the errno global in case someone writes:
204 // VLOG(..) << "The last error was " << strerror(errno)
205 int old_errno = errno;
207 // site_default normally points to FLAGS_v
208 int32* site_flag_value = site_default;
210 // Get basename for file
211 const char* base = strrchr(fname, '/');
212 base = base ? (base+1) : fname;
213 const char* base_end = strchr(base, '.');
214 size_t base_length = base_end ? (base_end - base) : strlen(base);
216 // Trim out trailing "-inl" if any
217 if (base_length >= 4 && (memcmp(base+base_length-4, "-inl", 4) == 0)) {
221 // TODO: Trim out _unittest suffix? Perhaps it is better to have
222 // the extra control and just leave it there.
224 // find target in vector of modules, replace site_flag_value with
225 // a module-specific verbose level, if any.
226 for (const VModuleInfo* info = vmodule_list;
227 info != NULL; info = info->next) {
228 if (SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(),
229 base, base_length)) {
230 site_flag_value = &info->vlog_level;
231 // value at info->vlog_level is now what controls
232 // the VLOG at the caller site forever
237 // Cache the vlog value pointer if --vmodule flag has been parsed.
238 ANNOTATE_BENIGN_RACE(site_flag,
239 "*site_flag may be written by several threads,"
240 " but the value will be the same");
241 if (read_vmodule_flag) *site_flag = site_flag_value;
243 // restore the errno in case something recoverable went wrong during
244 // the initialization of the VLOG mechanism (see above note "protect the..")
246 return *site_flag_value >= verbose_level;
249 _END_GOOGLE_NAMESPACE_