xref: /aosp_15_r20/system/logging/logd/SimpleLogBuffer.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker  *
4*598139dcSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker  *
8*598139dcSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker  *
10*598139dcSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker  * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker  */
16*598139dcSAndroid Build Coastguard Worker 
17*598139dcSAndroid Build Coastguard Worker #include "SimpleLogBuffer.h"
18*598139dcSAndroid Build Coastguard Worker 
19*598139dcSAndroid Build Coastguard Worker #include <android-base/logging.h>
20*598139dcSAndroid Build Coastguard Worker 
21*598139dcSAndroid Build Coastguard Worker #include "LogBufferElement.h"
22*598139dcSAndroid Build Coastguard Worker #include "LogSize.h"
23*598139dcSAndroid Build Coastguard Worker 
SimpleLogBuffer(LogReaderList * reader_list,LogTags * tags,LogStatistics * stats)24*598139dcSAndroid Build Coastguard Worker SimpleLogBuffer::SimpleLogBuffer(LogReaderList* reader_list, LogTags* tags, LogStatistics* stats)
25*598139dcSAndroid Build Coastguard Worker     : reader_list_(reader_list), tags_(tags), stats_(stats) {
26*598139dcSAndroid Build Coastguard Worker     Init();
27*598139dcSAndroid Build Coastguard Worker }
28*598139dcSAndroid Build Coastguard Worker 
~SimpleLogBuffer()29*598139dcSAndroid Build Coastguard Worker SimpleLogBuffer::~SimpleLogBuffer() {}
30*598139dcSAndroid Build Coastguard Worker 
Init()31*598139dcSAndroid Build Coastguard Worker void SimpleLogBuffer::Init() {
32*598139dcSAndroid Build Coastguard Worker     log_id_for_each(i) {
33*598139dcSAndroid Build Coastguard Worker         if (!SetSize(i, GetBufferSizeFromProperties(i))) {
34*598139dcSAndroid Build Coastguard Worker             SetSize(i, kLogBufferMinSize);
35*598139dcSAndroid Build Coastguard Worker         }
36*598139dcSAndroid Build Coastguard Worker     }
37*598139dcSAndroid Build Coastguard Worker 
38*598139dcSAndroid Build Coastguard Worker     // Release any sleeping reader threads to dump their current content.
39*598139dcSAndroid Build Coastguard Worker     auto lock = std::lock_guard{logd_lock};
40*598139dcSAndroid Build Coastguard Worker     for (const auto& reader_thread : reader_list_->running_reader_threads()) {
41*598139dcSAndroid Build Coastguard Worker         reader_thread->TriggerReader();
42*598139dcSAndroid Build Coastguard Worker     }
43*598139dcSAndroid Build Coastguard Worker }
44*598139dcSAndroid Build Coastguard Worker 
GetOldest(log_id_t log_id)45*598139dcSAndroid Build Coastguard Worker std::list<LogBufferElement>::iterator SimpleLogBuffer::GetOldest(log_id_t log_id) {
46*598139dcSAndroid Build Coastguard Worker     auto it = logs_.begin();
47*598139dcSAndroid Build Coastguard Worker     if (oldest_[log_id]) {
48*598139dcSAndroid Build Coastguard Worker         it = *oldest_[log_id];
49*598139dcSAndroid Build Coastguard Worker     }
50*598139dcSAndroid Build Coastguard Worker     while (it != logs_.end() && it->log_id() != log_id) {
51*598139dcSAndroid Build Coastguard Worker         it++;
52*598139dcSAndroid Build Coastguard Worker     }
53*598139dcSAndroid Build Coastguard Worker     if (it != logs_.end()) {
54*598139dcSAndroid Build Coastguard Worker         oldest_[log_id] = it;
55*598139dcSAndroid Build Coastguard Worker     }
56*598139dcSAndroid Build Coastguard Worker     return it;
57*598139dcSAndroid Build Coastguard Worker }
58*598139dcSAndroid Build Coastguard Worker 
ShouldLog(log_id_t log_id,const char * msg,uint16_t len)59*598139dcSAndroid Build Coastguard Worker bool SimpleLogBuffer::ShouldLog(log_id_t log_id, const char* msg, uint16_t len) {
60*598139dcSAndroid Build Coastguard Worker     if (log_id == LOG_ID_SECURITY) {
61*598139dcSAndroid Build Coastguard Worker         return true;
62*598139dcSAndroid Build Coastguard Worker     }
63*598139dcSAndroid Build Coastguard Worker 
64*598139dcSAndroid Build Coastguard Worker     int prio = ANDROID_LOG_INFO;
65*598139dcSAndroid Build Coastguard Worker     const char* tag = nullptr;
66*598139dcSAndroid Build Coastguard Worker     size_t tag_len = 0;
67*598139dcSAndroid Build Coastguard Worker     if (IsBinary(log_id)) {
68*598139dcSAndroid Build Coastguard Worker         int32_t numeric_tag = MsgToTag(msg, len);
69*598139dcSAndroid Build Coastguard Worker         tag = tags_->tagToName(numeric_tag);
70*598139dcSAndroid Build Coastguard Worker         if (tag) {
71*598139dcSAndroid Build Coastguard Worker             tag_len = strlen(tag);
72*598139dcSAndroid Build Coastguard Worker         }
73*598139dcSAndroid Build Coastguard Worker     } else {
74*598139dcSAndroid Build Coastguard Worker         prio = *msg;
75*598139dcSAndroid Build Coastguard Worker         tag = msg + 1;
76*598139dcSAndroid Build Coastguard Worker         tag_len = strnlen(tag, len - 1);
77*598139dcSAndroid Build Coastguard Worker     }
78*598139dcSAndroid Build Coastguard Worker     return __android_log_is_loggable_len(prio, tag, tag_len, ANDROID_LOG_VERBOSE);
79*598139dcSAndroid Build Coastguard Worker }
80*598139dcSAndroid Build Coastguard Worker 
Log(log_id_t log_id,log_time realtime,uid_t uid,pid_t pid,pid_t tid,const char * msg,uint16_t len)81*598139dcSAndroid Build Coastguard Worker int SimpleLogBuffer::Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
82*598139dcSAndroid Build Coastguard Worker                          const char* msg, uint16_t len) {
83*598139dcSAndroid Build Coastguard Worker     if (!__android_log_id_is_valid(log_id)) {
84*598139dcSAndroid Build Coastguard Worker         return -EINVAL;
85*598139dcSAndroid Build Coastguard Worker     }
86*598139dcSAndroid Build Coastguard Worker 
87*598139dcSAndroid Build Coastguard Worker     if (!ShouldLog(log_id, msg, len)) {
88*598139dcSAndroid Build Coastguard Worker         // Log traffic received to total
89*598139dcSAndroid Build Coastguard Worker         stats_->AddTotal(log_id, len);
90*598139dcSAndroid Build Coastguard Worker         return -EACCES;
91*598139dcSAndroid Build Coastguard Worker     }
92*598139dcSAndroid Build Coastguard Worker 
93*598139dcSAndroid Build Coastguard Worker     // Slip the time by 1 nsec if the incoming lands on xxxxxx000 ns.
94*598139dcSAndroid Build Coastguard Worker     // This prevents any chance that an outside source can request an
95*598139dcSAndroid Build Coastguard Worker     // exact entry with time specified in ms or us precision.
96*598139dcSAndroid Build Coastguard Worker     if ((realtime.tv_nsec % 1000) == 0) ++realtime.tv_nsec;
97*598139dcSAndroid Build Coastguard Worker 
98*598139dcSAndroid Build Coastguard Worker     auto lock = std::lock_guard{logd_lock};
99*598139dcSAndroid Build Coastguard Worker     auto sequence = sequence_.fetch_add(1, std::memory_order_relaxed);
100*598139dcSAndroid Build Coastguard Worker     LogInternal(LogBufferElement(log_id, realtime, uid, pid, tid, sequence, msg, len));
101*598139dcSAndroid Build Coastguard Worker     return len;
102*598139dcSAndroid Build Coastguard Worker }
103*598139dcSAndroid Build Coastguard Worker 
LogInternal(LogBufferElement && elem)104*598139dcSAndroid Build Coastguard Worker void SimpleLogBuffer::LogInternal(LogBufferElement&& elem) {
105*598139dcSAndroid Build Coastguard Worker     log_id_t log_id = elem.log_id();
106*598139dcSAndroid Build Coastguard Worker 
107*598139dcSAndroid Build Coastguard Worker     logs_.emplace_back(std::move(elem));
108*598139dcSAndroid Build Coastguard Worker     stats_->Add(logs_.back().ToLogStatisticsElement());
109*598139dcSAndroid Build Coastguard Worker     MaybePrune(log_id);
110*598139dcSAndroid Build Coastguard Worker     reader_list_->NotifyNewLog(1 << log_id);
111*598139dcSAndroid Build Coastguard Worker }
112*598139dcSAndroid Build Coastguard Worker 
CreateFlushToState(uint64_t start,LogMask log_mask)113*598139dcSAndroid Build Coastguard Worker std::unique_ptr<FlushToState> SimpleLogBuffer::CreateFlushToState(uint64_t start,
114*598139dcSAndroid Build Coastguard Worker                                                                   LogMask log_mask) {
115*598139dcSAndroid Build Coastguard Worker     return std::make_unique<FlushToState>(start, log_mask);
116*598139dcSAndroid Build Coastguard Worker }
117*598139dcSAndroid Build Coastguard Worker 
FlushTo(LogWriter * writer,FlushToState & abstract_state,const std::function<FilterResult (log_id_t log_id,pid_t pid,uint64_t sequence,log_time realtime)> & filter)118*598139dcSAndroid Build Coastguard Worker bool SimpleLogBuffer::FlushTo(
119*598139dcSAndroid Build Coastguard Worker         LogWriter* writer, FlushToState& abstract_state,
120*598139dcSAndroid Build Coastguard Worker         const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
121*598139dcSAndroid Build Coastguard Worker                                          log_time realtime)>& filter) {
122*598139dcSAndroid Build Coastguard Worker     auto& state = reinterpret_cast<FlushToState&>(abstract_state);
123*598139dcSAndroid Build Coastguard Worker 
124*598139dcSAndroid Build Coastguard Worker     std::list<LogBufferElement>::iterator it;
125*598139dcSAndroid Build Coastguard Worker     if (state.start() <= 1) {
126*598139dcSAndroid Build Coastguard Worker         // client wants to start from the beginning
127*598139dcSAndroid Build Coastguard Worker         it = logs_.begin();
128*598139dcSAndroid Build Coastguard Worker     } else {
129*598139dcSAndroid Build Coastguard Worker         // Client wants to start from some specified time. Chances are
130*598139dcSAndroid Build Coastguard Worker         // we are better off starting from the end of the time sorted list.
131*598139dcSAndroid Build Coastguard Worker         for (it = logs_.end(); it != logs_.begin();
132*598139dcSAndroid Build Coastguard Worker              /* do nothing */) {
133*598139dcSAndroid Build Coastguard Worker             --it;
134*598139dcSAndroid Build Coastguard Worker             if (it->sequence() == state.start()) {
135*598139dcSAndroid Build Coastguard Worker                 break;
136*598139dcSAndroid Build Coastguard Worker             } else if (it->sequence() < state.start()) {
137*598139dcSAndroid Build Coastguard Worker                 it++;
138*598139dcSAndroid Build Coastguard Worker                 break;
139*598139dcSAndroid Build Coastguard Worker             }
140*598139dcSAndroid Build Coastguard Worker         }
141*598139dcSAndroid Build Coastguard Worker     }
142*598139dcSAndroid Build Coastguard Worker 
143*598139dcSAndroid Build Coastguard Worker     for (; it != logs_.end(); ++it) {
144*598139dcSAndroid Build Coastguard Worker         LogBufferElement& element = *it;
145*598139dcSAndroid Build Coastguard Worker 
146*598139dcSAndroid Build Coastguard Worker         state.set_start(element.sequence());
147*598139dcSAndroid Build Coastguard Worker 
148*598139dcSAndroid Build Coastguard Worker         if (!writer->privileged() && element.uid() != writer->uid()) {
149*598139dcSAndroid Build Coastguard Worker             continue;
150*598139dcSAndroid Build Coastguard Worker         }
151*598139dcSAndroid Build Coastguard Worker 
152*598139dcSAndroid Build Coastguard Worker         if (((1 << element.log_id()) & state.log_mask()) == 0) {
153*598139dcSAndroid Build Coastguard Worker             continue;
154*598139dcSAndroid Build Coastguard Worker         }
155*598139dcSAndroid Build Coastguard Worker 
156*598139dcSAndroid Build Coastguard Worker         if (filter) {
157*598139dcSAndroid Build Coastguard Worker             FilterResult ret =
158*598139dcSAndroid Build Coastguard Worker                     filter(element.log_id(), element.pid(), element.sequence(), element.realtime());
159*598139dcSAndroid Build Coastguard Worker             if (ret == FilterResult::kSkip) {
160*598139dcSAndroid Build Coastguard Worker                 continue;
161*598139dcSAndroid Build Coastguard Worker             }
162*598139dcSAndroid Build Coastguard Worker             if (ret == FilterResult::kStop) {
163*598139dcSAndroid Build Coastguard Worker                 break;
164*598139dcSAndroid Build Coastguard Worker             }
165*598139dcSAndroid Build Coastguard Worker         }
166*598139dcSAndroid Build Coastguard Worker 
167*598139dcSAndroid Build Coastguard Worker         logd_lock.unlock();
168*598139dcSAndroid Build Coastguard Worker         // We never prune logs equal to or newer than any LogReaderThreads' `start` value, so the
169*598139dcSAndroid Build Coastguard Worker         // `element` pointer is safe here without the lock
170*598139dcSAndroid Build Coastguard Worker         if (!element.FlushTo(writer)) {
171*598139dcSAndroid Build Coastguard Worker             logd_lock.lock();
172*598139dcSAndroid Build Coastguard Worker             return false;
173*598139dcSAndroid Build Coastguard Worker         }
174*598139dcSAndroid Build Coastguard Worker         logd_lock.lock();
175*598139dcSAndroid Build Coastguard Worker     }
176*598139dcSAndroid Build Coastguard Worker 
177*598139dcSAndroid Build Coastguard Worker     state.set_start(state.start() + 1);
178*598139dcSAndroid Build Coastguard Worker     return true;
179*598139dcSAndroid Build Coastguard Worker }
180*598139dcSAndroid Build Coastguard Worker 
Clear(log_id_t id,uid_t uid)181*598139dcSAndroid Build Coastguard Worker bool SimpleLogBuffer::Clear(log_id_t id, uid_t uid) {
182*598139dcSAndroid Build Coastguard Worker     // Try three times to clear, then disconnect the readers and try one final time.
183*598139dcSAndroid Build Coastguard Worker     for (int retry = 0; retry < 3; ++retry) {
184*598139dcSAndroid Build Coastguard Worker         {
185*598139dcSAndroid Build Coastguard Worker             auto lock = std::lock_guard{logd_lock};
186*598139dcSAndroid Build Coastguard Worker             if (Prune(id, ULONG_MAX, uid)) {
187*598139dcSAndroid Build Coastguard Worker                 return true;
188*598139dcSAndroid Build Coastguard Worker             }
189*598139dcSAndroid Build Coastguard Worker         }
190*598139dcSAndroid Build Coastguard Worker         sleep(1);
191*598139dcSAndroid Build Coastguard Worker     }
192*598139dcSAndroid Build Coastguard Worker     // Check if it is still busy after the sleep, we try to prune one entry, not another clear run,
193*598139dcSAndroid Build Coastguard Worker     // so we are looking for the quick side effect of the return value to tell us if we have a
194*598139dcSAndroid Build Coastguard Worker     // _blocked_ reader.
195*598139dcSAndroid Build Coastguard Worker     bool busy = false;
196*598139dcSAndroid Build Coastguard Worker     {
197*598139dcSAndroid Build Coastguard Worker         auto lock = std::lock_guard{logd_lock};
198*598139dcSAndroid Build Coastguard Worker         busy = !Prune(id, 1, uid);
199*598139dcSAndroid Build Coastguard Worker     }
200*598139dcSAndroid Build Coastguard Worker     // It is still busy, disconnect all readers.
201*598139dcSAndroid Build Coastguard Worker     if (busy) {
202*598139dcSAndroid Build Coastguard Worker         auto lock = std::lock_guard{logd_lock};
203*598139dcSAndroid Build Coastguard Worker         for (const auto& reader_thread : reader_list_->running_reader_threads()) {
204*598139dcSAndroid Build Coastguard Worker             if (reader_thread->IsWatching(id)) {
205*598139dcSAndroid Build Coastguard Worker                 LOG(WARNING) << "Kicking blocked reader, " << reader_thread->name()
206*598139dcSAndroid Build Coastguard Worker                              << ", from LogBuffer::clear()";
207*598139dcSAndroid Build Coastguard Worker                 reader_thread->Release();
208*598139dcSAndroid Build Coastguard Worker             }
209*598139dcSAndroid Build Coastguard Worker         }
210*598139dcSAndroid Build Coastguard Worker     }
211*598139dcSAndroid Build Coastguard Worker     auto lock = std::lock_guard{logd_lock};
212*598139dcSAndroid Build Coastguard Worker     return Prune(id, ULONG_MAX, uid);
213*598139dcSAndroid Build Coastguard Worker }
214*598139dcSAndroid Build Coastguard Worker 
215*598139dcSAndroid Build Coastguard Worker // get the total space allocated to "id"
GetSize(log_id_t id)216*598139dcSAndroid Build Coastguard Worker size_t SimpleLogBuffer::GetSize(log_id_t id) {
217*598139dcSAndroid Build Coastguard Worker     auto lock = std::lock_guard{logd_lock};
218*598139dcSAndroid Build Coastguard Worker     size_t retval = max_size_[id];
219*598139dcSAndroid Build Coastguard Worker     return retval;
220*598139dcSAndroid Build Coastguard Worker }
221*598139dcSAndroid Build Coastguard Worker 
222*598139dcSAndroid Build Coastguard Worker // set the total space allocated to "id"
SetSize(log_id_t id,size_t size)223*598139dcSAndroid Build Coastguard Worker bool SimpleLogBuffer::SetSize(log_id_t id, size_t size) {
224*598139dcSAndroid Build Coastguard Worker     // Reasonable limits ...
225*598139dcSAndroid Build Coastguard Worker     if (!IsValidBufferSize(size)) {
226*598139dcSAndroid Build Coastguard Worker         return false;
227*598139dcSAndroid Build Coastguard Worker     }
228*598139dcSAndroid Build Coastguard Worker 
229*598139dcSAndroid Build Coastguard Worker     auto lock = std::lock_guard{logd_lock};
230*598139dcSAndroid Build Coastguard Worker     max_size_[id] = size;
231*598139dcSAndroid Build Coastguard Worker     return true;
232*598139dcSAndroid Build Coastguard Worker }
233*598139dcSAndroid Build Coastguard Worker 
MaybePrune(log_id_t id)234*598139dcSAndroid Build Coastguard Worker void SimpleLogBuffer::MaybePrune(log_id_t id) {
235*598139dcSAndroid Build Coastguard Worker     unsigned long prune_rows;
236*598139dcSAndroid Build Coastguard Worker     if (stats_->ShouldPrune(id, max_size_[id], &prune_rows)) {
237*598139dcSAndroid Build Coastguard Worker         Prune(id, prune_rows, 0);
238*598139dcSAndroid Build Coastguard Worker     }
239*598139dcSAndroid Build Coastguard Worker }
240*598139dcSAndroid Build Coastguard Worker 
Prune(log_id_t id,unsigned long prune_rows,uid_t caller_uid)241*598139dcSAndroid Build Coastguard Worker bool SimpleLogBuffer::Prune(log_id_t id, unsigned long prune_rows, uid_t caller_uid) {
242*598139dcSAndroid Build Coastguard Worker     // Don't prune logs that are newer than the point at which any reader threads are reading from.
243*598139dcSAndroid Build Coastguard Worker     LogReaderThread* oldest = nullptr;
244*598139dcSAndroid Build Coastguard Worker     for (const auto& reader_thread : reader_list_->running_reader_threads()) {
245*598139dcSAndroid Build Coastguard Worker         if (!reader_thread->IsWatching(id)) {
246*598139dcSAndroid Build Coastguard Worker             continue;
247*598139dcSAndroid Build Coastguard Worker         }
248*598139dcSAndroid Build Coastguard Worker         if (!oldest || oldest->start() > reader_thread->start() ||
249*598139dcSAndroid Build Coastguard Worker             (oldest->start() == reader_thread->start() &&
250*598139dcSAndroid Build Coastguard Worker              reader_thread->deadline().time_since_epoch().count() != 0)) {
251*598139dcSAndroid Build Coastguard Worker             oldest = reader_thread.get();
252*598139dcSAndroid Build Coastguard Worker         }
253*598139dcSAndroid Build Coastguard Worker     }
254*598139dcSAndroid Build Coastguard Worker 
255*598139dcSAndroid Build Coastguard Worker     auto it = GetOldest(id);
256*598139dcSAndroid Build Coastguard Worker 
257*598139dcSAndroid Build Coastguard Worker     while (it != logs_.end()) {
258*598139dcSAndroid Build Coastguard Worker         LogBufferElement& element = *it;
259*598139dcSAndroid Build Coastguard Worker 
260*598139dcSAndroid Build Coastguard Worker         if (element.log_id() != id) {
261*598139dcSAndroid Build Coastguard Worker             ++it;
262*598139dcSAndroid Build Coastguard Worker             continue;
263*598139dcSAndroid Build Coastguard Worker         }
264*598139dcSAndroid Build Coastguard Worker 
265*598139dcSAndroid Build Coastguard Worker         if (caller_uid != 0 && element.uid() != caller_uid) {
266*598139dcSAndroid Build Coastguard Worker             ++it;
267*598139dcSAndroid Build Coastguard Worker             continue;
268*598139dcSAndroid Build Coastguard Worker         }
269*598139dcSAndroid Build Coastguard Worker 
270*598139dcSAndroid Build Coastguard Worker         if (oldest && oldest->start() <= element.sequence()) {
271*598139dcSAndroid Build Coastguard Worker             KickReader(oldest, id, prune_rows);
272*598139dcSAndroid Build Coastguard Worker             return false;
273*598139dcSAndroid Build Coastguard Worker         }
274*598139dcSAndroid Build Coastguard Worker 
275*598139dcSAndroid Build Coastguard Worker         stats_->Subtract(element.ToLogStatisticsElement());
276*598139dcSAndroid Build Coastguard Worker         it = Erase(it);
277*598139dcSAndroid Build Coastguard Worker         if (--prune_rows == 0) {
278*598139dcSAndroid Build Coastguard Worker             return true;
279*598139dcSAndroid Build Coastguard Worker         }
280*598139dcSAndroid Build Coastguard Worker     }
281*598139dcSAndroid Build Coastguard Worker     return true;
282*598139dcSAndroid Build Coastguard Worker }
283*598139dcSAndroid Build Coastguard Worker 
Erase(std::list<LogBufferElement>::iterator it)284*598139dcSAndroid Build Coastguard Worker std::list<LogBufferElement>::iterator SimpleLogBuffer::Erase(
285*598139dcSAndroid Build Coastguard Worker         std::list<LogBufferElement>::iterator it) {
286*598139dcSAndroid Build Coastguard Worker     bool oldest_is_it[LOG_ID_MAX];
287*598139dcSAndroid Build Coastguard Worker     log_id_for_each(i) { oldest_is_it[i] = oldest_[i] && it == *oldest_[i]; }
288*598139dcSAndroid Build Coastguard Worker 
289*598139dcSAndroid Build Coastguard Worker     it = logs_.erase(it);
290*598139dcSAndroid Build Coastguard Worker 
291*598139dcSAndroid Build Coastguard Worker     log_id_for_each(i) {
292*598139dcSAndroid Build Coastguard Worker         if (oldest_is_it[i]) {
293*598139dcSAndroid Build Coastguard Worker             if (__predict_false(it == logs_.end())) {
294*598139dcSAndroid Build Coastguard Worker                 oldest_[i] = std::nullopt;
295*598139dcSAndroid Build Coastguard Worker             } else {
296*598139dcSAndroid Build Coastguard Worker                 oldest_[i] = it;  // Store the next iterator even if it does not correspond to
297*598139dcSAndroid Build Coastguard Worker                                   // the same log_id, as a starting point for GetOldest().
298*598139dcSAndroid Build Coastguard Worker             }
299*598139dcSAndroid Build Coastguard Worker         }
300*598139dcSAndroid Build Coastguard Worker     }
301*598139dcSAndroid Build Coastguard Worker 
302*598139dcSAndroid Build Coastguard Worker     return it;
303*598139dcSAndroid Build Coastguard Worker }
304*598139dcSAndroid Build Coastguard Worker 
305*598139dcSAndroid Build Coastguard Worker // If the selected reader is blocking our pruning progress, decide on
306*598139dcSAndroid Build Coastguard Worker // what kind of mitigation is necessary to unblock the situation.
KickReader(LogReaderThread * reader,log_id_t id,unsigned long prune_rows)307*598139dcSAndroid Build Coastguard Worker void SimpleLogBuffer::KickReader(LogReaderThread* reader, log_id_t id, unsigned long prune_rows) {
308*598139dcSAndroid Build Coastguard Worker     if (stats_->Sizes(id) > (2 * max_size_[id])) {  // +100%
309*598139dcSAndroid Build Coastguard Worker         // A misbehaving or slow reader has its connection
310*598139dcSAndroid Build Coastguard Worker         // dropped if we hit too much memory pressure.
311*598139dcSAndroid Build Coastguard Worker         LOG(WARNING) << "Kicking blocked reader, " << reader->name()
312*598139dcSAndroid Build Coastguard Worker                      << ", from LogBuffer::kickMe()";
313*598139dcSAndroid Build Coastguard Worker         reader->Release();
314*598139dcSAndroid Build Coastguard Worker     } else if (reader->deadline().time_since_epoch().count() != 0) {
315*598139dcSAndroid Build Coastguard Worker         // Allow a blocked WRAP deadline reader to trigger and start reporting the log data.
316*598139dcSAndroid Build Coastguard Worker         reader->TriggerReader();
317*598139dcSAndroid Build Coastguard Worker     } else {
318*598139dcSAndroid Build Coastguard Worker         // tell slow reader to skip entries to catch up
319*598139dcSAndroid Build Coastguard Worker         LOG(WARNING) << "Skipping " << prune_rows << " entries from slow reader, " << reader->name()
320*598139dcSAndroid Build Coastguard Worker                      << ", from LogBuffer::kickMe()";
321*598139dcSAndroid Build Coastguard Worker         reader->TriggerSkip(id, prune_rows);
322*598139dcSAndroid Build Coastguard Worker     }
323*598139dcSAndroid Build Coastguard Worker }
324