1*9356374aSAndroid Build Coastguard Worker // Copyright 2022 The Abseil Authors
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/log/internal/vlog_config.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <stddef.h>
18*9356374aSAndroid Build Coastguard Worker
19*9356374aSAndroid Build Coastguard Worker #include <algorithm>
20*9356374aSAndroid Build Coastguard Worker #include <atomic>
21*9356374aSAndroid Build Coastguard Worker #include <functional>
22*9356374aSAndroid Build Coastguard Worker #include <memory>
23*9356374aSAndroid Build Coastguard Worker #include <string>
24*9356374aSAndroid Build Coastguard Worker #include <utility>
25*9356374aSAndroid Build Coastguard Worker #include <vector>
26*9356374aSAndroid Build Coastguard Worker
27*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
28*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
29*9356374aSAndroid Build Coastguard Worker #include "absl/base/const_init.h"
30*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/spinlock.h"
31*9356374aSAndroid Build Coastguard Worker #include "absl/base/no_destructor.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
33*9356374aSAndroid Build Coastguard Worker #include "absl/base/thread_annotations.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/log/internal/fnmatch.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/strings/numbers.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_split.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/strings/strip.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/types/optional.h"
42*9356374aSAndroid Build Coastguard Worker
43*9356374aSAndroid Build Coastguard Worker namespace absl {
44*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
45*9356374aSAndroid Build Coastguard Worker namespace log_internal {
46*9356374aSAndroid Build Coastguard Worker
47*9356374aSAndroid Build Coastguard Worker namespace {
ModuleIsPath(absl::string_view module_pattern)48*9356374aSAndroid Build Coastguard Worker bool ModuleIsPath(absl::string_view module_pattern) {
49*9356374aSAndroid Build Coastguard Worker #ifdef _WIN32
50*9356374aSAndroid Build Coastguard Worker return module_pattern.find_first_of("/\\") != module_pattern.npos;
51*9356374aSAndroid Build Coastguard Worker #else
52*9356374aSAndroid Build Coastguard Worker return module_pattern.find('/') != module_pattern.npos;
53*9356374aSAndroid Build Coastguard Worker #endif
54*9356374aSAndroid Build Coastguard Worker }
55*9356374aSAndroid Build Coastguard Worker } // namespace
56*9356374aSAndroid Build Coastguard Worker
SlowIsEnabled(int stale_v,int level)57*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled(int stale_v, int level) {
58*9356374aSAndroid Build Coastguard Worker if (ABSL_PREDICT_TRUE(stale_v != kUninitialized)) {
59*9356374aSAndroid Build Coastguard Worker // Because of the prerequisites to this function, we know that stale_v is
60*9356374aSAndroid Build Coastguard Worker // either uninitialized or >= level. If it's not uninitialized, that means
61*9356374aSAndroid Build Coastguard Worker // it must be >= level, thus we should log.
62*9356374aSAndroid Build Coastguard Worker return true;
63*9356374aSAndroid Build Coastguard Worker }
64*9356374aSAndroid Build Coastguard Worker stale_v = log_internal::RegisterAndInitialize(this);
65*9356374aSAndroid Build Coastguard Worker return ABSL_PREDICT_FALSE(stale_v >= level);
66*9356374aSAndroid Build Coastguard Worker }
67*9356374aSAndroid Build Coastguard Worker
SlowIsEnabled0(int stale_v)68*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled0(int stale_v) { return SlowIsEnabled(stale_v, 0); }
SlowIsEnabled1(int stale_v)69*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled1(int stale_v) { return SlowIsEnabled(stale_v, 1); }
SlowIsEnabled2(int stale_v)70*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled2(int stale_v) { return SlowIsEnabled(stale_v, 2); }
SlowIsEnabled3(int stale_v)71*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled3(int stale_v) { return SlowIsEnabled(stale_v, 3); }
SlowIsEnabled4(int stale_v)72*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled4(int stale_v) { return SlowIsEnabled(stale_v, 4); }
SlowIsEnabled5(int stale_v)73*9356374aSAndroid Build Coastguard Worker bool VLogSite::SlowIsEnabled5(int stale_v) { return SlowIsEnabled(stale_v, 5); }
74*9356374aSAndroid Build Coastguard Worker
75*9356374aSAndroid Build Coastguard Worker namespace {
76*9356374aSAndroid Build Coastguard Worker struct VModuleInfo final {
77*9356374aSAndroid Build Coastguard Worker std::string module_pattern;
78*9356374aSAndroid Build Coastguard Worker bool module_is_path; // i.e. it contains a path separator.
79*9356374aSAndroid Build Coastguard Worker int vlog_level;
80*9356374aSAndroid Build Coastguard Worker
81*9356374aSAndroid Build Coastguard Worker // Allocates memory.
VModuleInfoabsl::log_internal::__anon034fec250211::VModuleInfo82*9356374aSAndroid Build Coastguard Worker VModuleInfo(absl::string_view module_pattern_arg, bool module_is_path_arg,
83*9356374aSAndroid Build Coastguard Worker int vlog_level_arg)
84*9356374aSAndroid Build Coastguard Worker : module_pattern(std::string(module_pattern_arg)),
85*9356374aSAndroid Build Coastguard Worker module_is_path(module_is_path_arg),
86*9356374aSAndroid Build Coastguard Worker vlog_level(vlog_level_arg) {}
87*9356374aSAndroid Build Coastguard Worker };
88*9356374aSAndroid Build Coastguard Worker
89*9356374aSAndroid Build Coastguard Worker // `mutex` guards all of the data structures that aren't lock-free.
90*9356374aSAndroid Build Coastguard Worker // To avoid problems with the heap checker which calls into `VLOG`, `mutex` must
91*9356374aSAndroid Build Coastguard Worker // be a `SpinLock` that prevents fiber scheduling instead of a `Mutex`.
92*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT absl::base_internal::SpinLock mutex(
93*9356374aSAndroid Build Coastguard Worker absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
94*9356374aSAndroid Build Coastguard Worker
95*9356374aSAndroid Build Coastguard Worker // `GetUpdateSitesMutex()` serializes updates to all of the sites (i.e. those in
96*9356374aSAndroid Build Coastguard Worker // `site_list_head`) themselves.
GetUpdateSitesMutex()97*9356374aSAndroid Build Coastguard Worker absl::Mutex* GetUpdateSitesMutex() {
98*9356374aSAndroid Build Coastguard Worker // Chromium requires no global destructors, so we can't use the
99*9356374aSAndroid Build Coastguard Worker // absl::kConstInit idiom since absl::Mutex as a non-trivial destructor.
100*9356374aSAndroid Build Coastguard Worker static absl::NoDestructor<absl::Mutex> update_sites_mutex ABSL_ACQUIRED_AFTER(
101*9356374aSAndroid Build Coastguard Worker mutex);
102*9356374aSAndroid Build Coastguard Worker return update_sites_mutex.get();
103*9356374aSAndroid Build Coastguard Worker }
104*9356374aSAndroid Build Coastguard Worker
105*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT int global_v ABSL_GUARDED_BY(mutex) = 0;
106*9356374aSAndroid Build Coastguard Worker // `site_list_head` is the head of a singly-linked list. Traversal, insertion,
107*9356374aSAndroid Build Coastguard Worker // and reads are atomic, so no locks are required, but updates to existing
108*9356374aSAndroid Build Coastguard Worker // elements are guarded by `GetUpdateSitesMutex()`.
109*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::atomic<VLogSite*> site_list_head{nullptr};
ABSL_GUARDED_BY(mutex)110*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::vector<VModuleInfo>* vmodule_info ABSL_GUARDED_BY(mutex)
111*9356374aSAndroid Build Coastguard Worker ABSL_PT_GUARDED_BY(mutex){nullptr};
112*9356374aSAndroid Build Coastguard Worker
113*9356374aSAndroid Build Coastguard Worker // Only used for lisp.
114*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::vector<std::function<void()>>* update_callbacks
ABSL_GUARDED_BY(GetUpdateSitesMutex ())115*9356374aSAndroid Build Coastguard Worker ABSL_GUARDED_BY(GetUpdateSitesMutex())
116*9356374aSAndroid Build Coastguard Worker ABSL_PT_GUARDED_BY(GetUpdateSitesMutex()){nullptr};
117*9356374aSAndroid Build Coastguard Worker
118*9356374aSAndroid Build Coastguard Worker // Allocates memory.
get_vmodule_info()119*9356374aSAndroid Build Coastguard Worker std::vector<VModuleInfo>& get_vmodule_info()
120*9356374aSAndroid Build Coastguard Worker ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) {
121*9356374aSAndroid Build Coastguard Worker if (!vmodule_info) vmodule_info = new std::vector<VModuleInfo>;
122*9356374aSAndroid Build Coastguard Worker return *vmodule_info;
123*9356374aSAndroid Build Coastguard Worker }
124*9356374aSAndroid Build Coastguard Worker
125*9356374aSAndroid Build Coastguard Worker // Does not allocate or take locks.
VLogLevel(absl::string_view file,const std::vector<VModuleInfo> * infos,int current_global_v)126*9356374aSAndroid Build Coastguard Worker int VLogLevel(absl::string_view file, const std::vector<VModuleInfo>* infos,
127*9356374aSAndroid Build Coastguard Worker int current_global_v) {
128*9356374aSAndroid Build Coastguard Worker // `infos` is null during a call to `VLOG` prior to setting `vmodule` (e.g. by
129*9356374aSAndroid Build Coastguard Worker // parsing flags). We can't allocate in `VLOG`, so we treat null as empty
130*9356374aSAndroid Build Coastguard Worker // here and press on.
131*9356374aSAndroid Build Coastguard Worker if (!infos || infos->empty()) return current_global_v;
132*9356374aSAndroid Build Coastguard Worker // Get basename for file
133*9356374aSAndroid Build Coastguard Worker absl::string_view basename = file;
134*9356374aSAndroid Build Coastguard Worker {
135*9356374aSAndroid Build Coastguard Worker const size_t sep = basename.rfind('/');
136*9356374aSAndroid Build Coastguard Worker if (sep != basename.npos) {
137*9356374aSAndroid Build Coastguard Worker basename.remove_prefix(sep + 1);
138*9356374aSAndroid Build Coastguard Worker #ifdef _WIN32
139*9356374aSAndroid Build Coastguard Worker } else {
140*9356374aSAndroid Build Coastguard Worker const size_t sep = basename.rfind('\\');
141*9356374aSAndroid Build Coastguard Worker if (sep != basename.npos) basename.remove_prefix(sep + 1);
142*9356374aSAndroid Build Coastguard Worker #endif
143*9356374aSAndroid Build Coastguard Worker }
144*9356374aSAndroid Build Coastguard Worker }
145*9356374aSAndroid Build Coastguard Worker
146*9356374aSAndroid Build Coastguard Worker absl::string_view stem = file, stem_basename = basename;
147*9356374aSAndroid Build Coastguard Worker {
148*9356374aSAndroid Build Coastguard Worker const size_t sep = stem_basename.find('.');
149*9356374aSAndroid Build Coastguard Worker if (sep != stem_basename.npos) {
150*9356374aSAndroid Build Coastguard Worker stem.remove_suffix(stem_basename.size() - sep);
151*9356374aSAndroid Build Coastguard Worker stem_basename.remove_suffix(stem_basename.size() - sep);
152*9356374aSAndroid Build Coastguard Worker }
153*9356374aSAndroid Build Coastguard Worker if (absl::ConsumeSuffix(&stem_basename, "-inl")) {
154*9356374aSAndroid Build Coastguard Worker stem.remove_suffix(absl::string_view("-inl").size());
155*9356374aSAndroid Build Coastguard Worker }
156*9356374aSAndroid Build Coastguard Worker }
157*9356374aSAndroid Build Coastguard Worker for (const auto& info : *infos) {
158*9356374aSAndroid Build Coastguard Worker if (info.module_is_path) {
159*9356374aSAndroid Build Coastguard Worker // If there are any slashes in the pattern, try to match the full
160*9356374aSAndroid Build Coastguard Worker // name.
161*9356374aSAndroid Build Coastguard Worker if (FNMatch(info.module_pattern, stem)) {
162*9356374aSAndroid Build Coastguard Worker return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level;
163*9356374aSAndroid Build Coastguard Worker }
164*9356374aSAndroid Build Coastguard Worker } else if (FNMatch(info.module_pattern, stem_basename)) {
165*9356374aSAndroid Build Coastguard Worker return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level;
166*9356374aSAndroid Build Coastguard Worker }
167*9356374aSAndroid Build Coastguard Worker }
168*9356374aSAndroid Build Coastguard Worker
169*9356374aSAndroid Build Coastguard Worker return current_global_v;
170*9356374aSAndroid Build Coastguard Worker }
171*9356374aSAndroid Build Coastguard Worker
172*9356374aSAndroid Build Coastguard Worker // Allocates memory.
AppendVModuleLocked(absl::string_view module_pattern,int log_level)173*9356374aSAndroid Build Coastguard Worker int AppendVModuleLocked(absl::string_view module_pattern, int log_level)
174*9356374aSAndroid Build Coastguard Worker ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) {
175*9356374aSAndroid Build Coastguard Worker for (const auto& info : get_vmodule_info()) {
176*9356374aSAndroid Build Coastguard Worker if (FNMatch(info.module_pattern, module_pattern)) {
177*9356374aSAndroid Build Coastguard Worker // This is a memory optimization to avoid storing patterns that will never
178*9356374aSAndroid Build Coastguard Worker // match due to exit early semantics. Primarily optimized for our own unit
179*9356374aSAndroid Build Coastguard Worker // tests.
180*9356374aSAndroid Build Coastguard Worker return info.vlog_level;
181*9356374aSAndroid Build Coastguard Worker }
182*9356374aSAndroid Build Coastguard Worker }
183*9356374aSAndroid Build Coastguard Worker bool module_is_path = ModuleIsPath(module_pattern);
184*9356374aSAndroid Build Coastguard Worker get_vmodule_info().emplace_back(std::string(module_pattern), module_is_path,
185*9356374aSAndroid Build Coastguard Worker log_level);
186*9356374aSAndroid Build Coastguard Worker return global_v;
187*9356374aSAndroid Build Coastguard Worker }
188*9356374aSAndroid Build Coastguard Worker
189*9356374aSAndroid Build Coastguard Worker // Allocates memory.
PrependVModuleLocked(absl::string_view module_pattern,int log_level)190*9356374aSAndroid Build Coastguard Worker int PrependVModuleLocked(absl::string_view module_pattern, int log_level)
191*9356374aSAndroid Build Coastguard Worker ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) {
192*9356374aSAndroid Build Coastguard Worker absl::optional<int> old_log_level;
193*9356374aSAndroid Build Coastguard Worker for (const auto& info : get_vmodule_info()) {
194*9356374aSAndroid Build Coastguard Worker if (FNMatch(info.module_pattern, module_pattern)) {
195*9356374aSAndroid Build Coastguard Worker old_log_level = info.vlog_level;
196*9356374aSAndroid Build Coastguard Worker break;
197*9356374aSAndroid Build Coastguard Worker }
198*9356374aSAndroid Build Coastguard Worker }
199*9356374aSAndroid Build Coastguard Worker bool module_is_path = ModuleIsPath(module_pattern);
200*9356374aSAndroid Build Coastguard Worker auto iter = get_vmodule_info().emplace(get_vmodule_info().cbegin(),
201*9356374aSAndroid Build Coastguard Worker std::string(module_pattern),
202*9356374aSAndroid Build Coastguard Worker module_is_path, log_level);
203*9356374aSAndroid Build Coastguard Worker
204*9356374aSAndroid Build Coastguard Worker // This is a memory optimization to avoid storing patterns that will never
205*9356374aSAndroid Build Coastguard Worker // match due to exit early semantics. Primarily optimized for our own unit
206*9356374aSAndroid Build Coastguard Worker // tests.
207*9356374aSAndroid Build Coastguard Worker get_vmodule_info().erase(
208*9356374aSAndroid Build Coastguard Worker std::remove_if(++iter, get_vmodule_info().end(),
209*9356374aSAndroid Build Coastguard Worker [module_pattern](const VModuleInfo& info) {
210*9356374aSAndroid Build Coastguard Worker return FNMatch(info.module_pattern, module_pattern);
211*9356374aSAndroid Build Coastguard Worker }),
212*9356374aSAndroid Build Coastguard Worker get_vmodule_info().cend());
213*9356374aSAndroid Build Coastguard Worker return old_log_level.value_or(global_v);
214*9356374aSAndroid Build Coastguard Worker }
215*9356374aSAndroid Build Coastguard Worker } // namespace
216*9356374aSAndroid Build Coastguard Worker
VLogLevel(absl::string_view file)217*9356374aSAndroid Build Coastguard Worker int VLogLevel(absl::string_view file) ABSL_LOCKS_EXCLUDED(mutex) {
218*9356374aSAndroid Build Coastguard Worker absl::base_internal::SpinLockHolder l(&mutex);
219*9356374aSAndroid Build Coastguard Worker return VLogLevel(file, vmodule_info, global_v);
220*9356374aSAndroid Build Coastguard Worker }
221*9356374aSAndroid Build Coastguard Worker
RegisterAndInitialize(VLogSite * v)222*9356374aSAndroid Build Coastguard Worker int RegisterAndInitialize(VLogSite* v) ABSL_LOCKS_EXCLUDED(mutex) {
223*9356374aSAndroid Build Coastguard Worker // std::memory_order_seq_cst is overkill in this function, but given that this
224*9356374aSAndroid Build Coastguard Worker // path is intended to be slow, it's not worth the brain power to relax that.
225*9356374aSAndroid Build Coastguard Worker VLogSite* h = site_list_head.load(std::memory_order_seq_cst);
226*9356374aSAndroid Build Coastguard Worker
227*9356374aSAndroid Build Coastguard Worker VLogSite* old = nullptr;
228*9356374aSAndroid Build Coastguard Worker if (v->next_.compare_exchange_strong(old, h, std::memory_order_seq_cst,
229*9356374aSAndroid Build Coastguard Worker std::memory_order_seq_cst)) {
230*9356374aSAndroid Build Coastguard Worker // Multiple threads may attempt to register this site concurrently.
231*9356374aSAndroid Build Coastguard Worker // By successfully setting `v->next` this thread commits to being *the*
232*9356374aSAndroid Build Coastguard Worker // thread that installs `v` in the list.
233*9356374aSAndroid Build Coastguard Worker while (!site_list_head.compare_exchange_weak(
234*9356374aSAndroid Build Coastguard Worker h, v, std::memory_order_seq_cst, std::memory_order_seq_cst)) {
235*9356374aSAndroid Build Coastguard Worker v->next_.store(h, std::memory_order_seq_cst);
236*9356374aSAndroid Build Coastguard Worker }
237*9356374aSAndroid Build Coastguard Worker }
238*9356374aSAndroid Build Coastguard Worker
239*9356374aSAndroid Build Coastguard Worker int old_v = VLogSite::kUninitialized;
240*9356374aSAndroid Build Coastguard Worker int new_v = VLogLevel(v->file_);
241*9356374aSAndroid Build Coastguard Worker // No loop, if someone else set this, we should respect their evaluation of
242*9356374aSAndroid Build Coastguard Worker // `VLogLevel`. This may mean we return a stale `v`, but `v` itself will
243*9356374aSAndroid Build Coastguard Worker // always arrive at the freshest value. Otherwise, we could be writing a
244*9356374aSAndroid Build Coastguard Worker // stale value and clobbering the fresher one.
245*9356374aSAndroid Build Coastguard Worker if (v->v_.compare_exchange_strong(old_v, new_v, std::memory_order_seq_cst,
246*9356374aSAndroid Build Coastguard Worker std::memory_order_seq_cst)) {
247*9356374aSAndroid Build Coastguard Worker return new_v;
248*9356374aSAndroid Build Coastguard Worker }
249*9356374aSAndroid Build Coastguard Worker return old_v;
250*9356374aSAndroid Build Coastguard Worker }
251*9356374aSAndroid Build Coastguard Worker
UpdateVLogSites()252*9356374aSAndroid Build Coastguard Worker void UpdateVLogSites() ABSL_UNLOCK_FUNCTION(mutex)
253*9356374aSAndroid Build Coastguard Worker ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) {
254*9356374aSAndroid Build Coastguard Worker std::vector<VModuleInfo> infos = get_vmodule_info();
255*9356374aSAndroid Build Coastguard Worker int current_global_v = global_v;
256*9356374aSAndroid Build Coastguard Worker // We need to grab `GetUpdateSitesMutex()` before we release `mutex` to ensure
257*9356374aSAndroid Build Coastguard Worker // that updates are not interleaved (resulting in an inconsistent final state)
258*9356374aSAndroid Build Coastguard Worker // and to ensure that the final state in the sites matches the final state of
259*9356374aSAndroid Build Coastguard Worker // `vmodule_info`. We unlock `mutex` to ensure that uninitialized sites don't
260*9356374aSAndroid Build Coastguard Worker // have to wait on all updates in order to acquire `mutex` and initialize
261*9356374aSAndroid Build Coastguard Worker // themselves.
262*9356374aSAndroid Build Coastguard Worker absl::MutexLock ul(GetUpdateSitesMutex());
263*9356374aSAndroid Build Coastguard Worker mutex.Unlock();
264*9356374aSAndroid Build Coastguard Worker VLogSite* n = site_list_head.load(std::memory_order_seq_cst);
265*9356374aSAndroid Build Coastguard Worker // Because sites are added to the list in the order they are executed, there
266*9356374aSAndroid Build Coastguard Worker // tend to be clusters of entries with the same file.
267*9356374aSAndroid Build Coastguard Worker const char* last_file = nullptr;
268*9356374aSAndroid Build Coastguard Worker int last_file_level = 0;
269*9356374aSAndroid Build Coastguard Worker while (n != nullptr) {
270*9356374aSAndroid Build Coastguard Worker if (n->file_ != last_file) {
271*9356374aSAndroid Build Coastguard Worker last_file = n->file_;
272*9356374aSAndroid Build Coastguard Worker last_file_level = VLogLevel(n->file_, &infos, current_global_v);
273*9356374aSAndroid Build Coastguard Worker }
274*9356374aSAndroid Build Coastguard Worker n->v_.store(last_file_level, std::memory_order_seq_cst);
275*9356374aSAndroid Build Coastguard Worker n = n->next_.load(std::memory_order_seq_cst);
276*9356374aSAndroid Build Coastguard Worker }
277*9356374aSAndroid Build Coastguard Worker if (update_callbacks) {
278*9356374aSAndroid Build Coastguard Worker for (auto& cb : *update_callbacks) {
279*9356374aSAndroid Build Coastguard Worker cb();
280*9356374aSAndroid Build Coastguard Worker }
281*9356374aSAndroid Build Coastguard Worker }
282*9356374aSAndroid Build Coastguard Worker }
283*9356374aSAndroid Build Coastguard Worker
UpdateVModule(absl::string_view vmodule)284*9356374aSAndroid Build Coastguard Worker void UpdateVModule(absl::string_view vmodule)
285*9356374aSAndroid Build Coastguard Worker ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) {
286*9356374aSAndroid Build Coastguard Worker std::vector<std::pair<absl::string_view, int>> glob_levels;
287*9356374aSAndroid Build Coastguard Worker for (absl::string_view glob_level : absl::StrSplit(vmodule, ',')) {
288*9356374aSAndroid Build Coastguard Worker const size_t eq = glob_level.rfind('=');
289*9356374aSAndroid Build Coastguard Worker if (eq == glob_level.npos) continue;
290*9356374aSAndroid Build Coastguard Worker const absl::string_view glob = glob_level.substr(0, eq);
291*9356374aSAndroid Build Coastguard Worker int level;
292*9356374aSAndroid Build Coastguard Worker if (!absl::SimpleAtoi(glob_level.substr(eq + 1), &level)) continue;
293*9356374aSAndroid Build Coastguard Worker glob_levels.emplace_back(glob, level);
294*9356374aSAndroid Build Coastguard Worker }
295*9356374aSAndroid Build Coastguard Worker mutex.Lock(); // Unlocked by UpdateVLogSites().
296*9356374aSAndroid Build Coastguard Worker get_vmodule_info().clear();
297*9356374aSAndroid Build Coastguard Worker for (const auto& it : glob_levels) {
298*9356374aSAndroid Build Coastguard Worker const absl::string_view glob = it.first;
299*9356374aSAndroid Build Coastguard Worker const int level = it.second;
300*9356374aSAndroid Build Coastguard Worker AppendVModuleLocked(glob, level);
301*9356374aSAndroid Build Coastguard Worker }
302*9356374aSAndroid Build Coastguard Worker UpdateVLogSites();
303*9356374aSAndroid Build Coastguard Worker }
304*9356374aSAndroid Build Coastguard Worker
UpdateGlobalVLogLevel(int v)305*9356374aSAndroid Build Coastguard Worker int UpdateGlobalVLogLevel(int v)
306*9356374aSAndroid Build Coastguard Worker ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) {
307*9356374aSAndroid Build Coastguard Worker mutex.Lock(); // Unlocked by UpdateVLogSites().
308*9356374aSAndroid Build Coastguard Worker const int old_global_v = global_v;
309*9356374aSAndroid Build Coastguard Worker if (v == global_v) {
310*9356374aSAndroid Build Coastguard Worker mutex.Unlock();
311*9356374aSAndroid Build Coastguard Worker return old_global_v;
312*9356374aSAndroid Build Coastguard Worker }
313*9356374aSAndroid Build Coastguard Worker global_v = v;
314*9356374aSAndroid Build Coastguard Worker UpdateVLogSites();
315*9356374aSAndroid Build Coastguard Worker return old_global_v;
316*9356374aSAndroid Build Coastguard Worker }
317*9356374aSAndroid Build Coastguard Worker
PrependVModule(absl::string_view module_pattern,int log_level)318*9356374aSAndroid Build Coastguard Worker int PrependVModule(absl::string_view module_pattern, int log_level)
319*9356374aSAndroid Build Coastguard Worker ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) {
320*9356374aSAndroid Build Coastguard Worker mutex.Lock(); // Unlocked by UpdateVLogSites().
321*9356374aSAndroid Build Coastguard Worker int old_v = PrependVModuleLocked(module_pattern, log_level);
322*9356374aSAndroid Build Coastguard Worker UpdateVLogSites();
323*9356374aSAndroid Build Coastguard Worker return old_v;
324*9356374aSAndroid Build Coastguard Worker }
325*9356374aSAndroid Build Coastguard Worker
OnVLogVerbosityUpdate(std::function<void ()> cb)326*9356374aSAndroid Build Coastguard Worker void OnVLogVerbosityUpdate(std::function<void()> cb)
327*9356374aSAndroid Build Coastguard Worker ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) {
328*9356374aSAndroid Build Coastguard Worker absl::MutexLock ul(GetUpdateSitesMutex());
329*9356374aSAndroid Build Coastguard Worker if (!update_callbacks)
330*9356374aSAndroid Build Coastguard Worker update_callbacks = new std::vector<std::function<void()>>;
331*9356374aSAndroid Build Coastguard Worker update_callbacks->push_back(std::move(cb));
332*9356374aSAndroid Build Coastguard Worker }
333*9356374aSAndroid Build Coastguard Worker
SetVModuleListHeadForTestOnly(VLogSite * v)334*9356374aSAndroid Build Coastguard Worker VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v) {
335*9356374aSAndroid Build Coastguard Worker return site_list_head.exchange(v, std::memory_order_seq_cst);
336*9356374aSAndroid Build Coastguard Worker }
337*9356374aSAndroid Build Coastguard Worker
338*9356374aSAndroid Build Coastguard Worker } // namespace log_internal
339*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
340*9356374aSAndroid Build Coastguard Worker } // namespace absl
341