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 "SerializedLogBuffer.h"
18*598139dcSAndroid Build Coastguard Worker
19*598139dcSAndroid Build Coastguard Worker #include <sys/prctl.h>
20*598139dcSAndroid Build Coastguard Worker
21*598139dcSAndroid Build Coastguard Worker #include <limits>
22*598139dcSAndroid Build Coastguard Worker
23*598139dcSAndroid Build Coastguard Worker #include <android-base/logging.h>
24*598139dcSAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
25*598139dcSAndroid Build Coastguard Worker
26*598139dcSAndroid Build Coastguard Worker #include "LogSize.h"
27*598139dcSAndroid Build Coastguard Worker #include "LogStatistics.h"
28*598139dcSAndroid Build Coastguard Worker #include "SerializedFlushToState.h"
29*598139dcSAndroid Build Coastguard Worker
LogToLogBuffer(std::list<SerializedLogChunk> & log_buffer,size_t max_size,uint64_t sequence,log_time realtime,uid_t uid,pid_t pid,pid_t tid,const char * msg,uint16_t len)30*598139dcSAndroid Build Coastguard Worker static SerializedLogEntry* LogToLogBuffer(std::list<SerializedLogChunk>& log_buffer,
31*598139dcSAndroid Build Coastguard Worker size_t max_size, uint64_t sequence, log_time realtime,
32*598139dcSAndroid Build Coastguard Worker uid_t uid, pid_t pid, pid_t tid, const char* msg,
33*598139dcSAndroid Build Coastguard Worker uint16_t len) {
34*598139dcSAndroid Build Coastguard Worker if (log_buffer.empty()) {
35*598139dcSAndroid Build Coastguard Worker log_buffer.push_back(SerializedLogChunk(max_size / SerializedLogBuffer::kChunkSizeDivisor));
36*598139dcSAndroid Build Coastguard Worker }
37*598139dcSAndroid Build Coastguard Worker
38*598139dcSAndroid Build Coastguard Worker auto total_len = sizeof(SerializedLogEntry) + len;
39*598139dcSAndroid Build Coastguard Worker if (!log_buffer.back().CanLog(total_len)) {
40*598139dcSAndroid Build Coastguard Worker log_buffer.back().FinishWriting();
41*598139dcSAndroid Build Coastguard Worker log_buffer.push_back(SerializedLogChunk(max_size / SerializedLogBuffer::kChunkSizeDivisor));
42*598139dcSAndroid Build Coastguard Worker }
43*598139dcSAndroid Build Coastguard Worker
44*598139dcSAndroid Build Coastguard Worker return log_buffer.back().Log(sequence, realtime, uid, pid, tid, msg, len);
45*598139dcSAndroid Build Coastguard Worker }
46*598139dcSAndroid Build Coastguard Worker
47*598139dcSAndroid Build Coastguard Worker // Clear all logs from a particular UID by iterating through all existing logs for a log_id, and
48*598139dcSAndroid Build Coastguard Worker // write all logs that don't match the UID into a new log buffer, then swapping the log buffers.
49*598139dcSAndroid Build Coastguard Worker // There is an optimization that chunks are copied as-is until a log message from the UID is found,
50*598139dcSAndroid Build Coastguard Worker // to ensure that back-to-back clears of the same UID do not require reflowing the entire buffer.
ClearLogsByUid(std::list<SerializedLogChunk> & log_buffer,uid_t uid,size_t max_size,log_id_t log_id,LogStatistics * stats)51*598139dcSAndroid Build Coastguard Worker void ClearLogsByUid(std::list<SerializedLogChunk>& log_buffer, uid_t uid, size_t max_size,
52*598139dcSAndroid Build Coastguard Worker log_id_t log_id, LogStatistics* stats) REQUIRES(logd_lock) {
53*598139dcSAndroid Build Coastguard Worker bool contains_uid_logs = false;
54*598139dcSAndroid Build Coastguard Worker std::list<SerializedLogChunk> new_logs;
55*598139dcSAndroid Build Coastguard Worker auto it = log_buffer.begin();
56*598139dcSAndroid Build Coastguard Worker while (it != log_buffer.end()) {
57*598139dcSAndroid Build Coastguard Worker auto chunk = it++;
58*598139dcSAndroid Build Coastguard Worker chunk->NotifyReadersOfPrune(log_id);
59*598139dcSAndroid Build Coastguard Worker chunk->IncReaderRefCount();
60*598139dcSAndroid Build Coastguard Worker
61*598139dcSAndroid Build Coastguard Worker if (!contains_uid_logs) {
62*598139dcSAndroid Build Coastguard Worker for (const auto& entry : *chunk) {
63*598139dcSAndroid Build Coastguard Worker if (entry.uid() == uid) {
64*598139dcSAndroid Build Coastguard Worker contains_uid_logs = true;
65*598139dcSAndroid Build Coastguard Worker break;
66*598139dcSAndroid Build Coastguard Worker }
67*598139dcSAndroid Build Coastguard Worker }
68*598139dcSAndroid Build Coastguard Worker if (!contains_uid_logs) {
69*598139dcSAndroid Build Coastguard Worker chunk->DecReaderRefCount();
70*598139dcSAndroid Build Coastguard Worker new_logs.splice(new_logs.end(), log_buffer, chunk);
71*598139dcSAndroid Build Coastguard Worker continue;
72*598139dcSAndroid Build Coastguard Worker }
73*598139dcSAndroid Build Coastguard Worker // We found a UID log, so push a writable chunk to prepare for the next loop.
74*598139dcSAndroid Build Coastguard Worker new_logs.push_back(
75*598139dcSAndroid Build Coastguard Worker SerializedLogChunk(max_size / SerializedLogBuffer::kChunkSizeDivisor));
76*598139dcSAndroid Build Coastguard Worker }
77*598139dcSAndroid Build Coastguard Worker
78*598139dcSAndroid Build Coastguard Worker for (const auto& entry : *chunk) {
79*598139dcSAndroid Build Coastguard Worker if (entry.uid() == uid) {
80*598139dcSAndroid Build Coastguard Worker if (stats != nullptr) {
81*598139dcSAndroid Build Coastguard Worker stats->Subtract(entry.ToLogStatisticsElement(log_id));
82*598139dcSAndroid Build Coastguard Worker }
83*598139dcSAndroid Build Coastguard Worker } else {
84*598139dcSAndroid Build Coastguard Worker LogToLogBuffer(new_logs, max_size, entry.sequence(), entry.realtime(), entry.uid(),
85*598139dcSAndroid Build Coastguard Worker entry.pid(), entry.tid(), entry.msg(), entry.msg_len());
86*598139dcSAndroid Build Coastguard Worker }
87*598139dcSAndroid Build Coastguard Worker }
88*598139dcSAndroid Build Coastguard Worker chunk->DecReaderRefCount();
89*598139dcSAndroid Build Coastguard Worker log_buffer.erase(chunk);
90*598139dcSAndroid Build Coastguard Worker }
91*598139dcSAndroid Build Coastguard Worker std::swap(new_logs, log_buffer);
92*598139dcSAndroid Build Coastguard Worker }
93*598139dcSAndroid Build Coastguard Worker
SerializedLogBuffer(LogReaderList * reader_list,LogTags * tags,LogStatistics * stats)94*598139dcSAndroid Build Coastguard Worker SerializedLogBuffer::SerializedLogBuffer(LogReaderList* reader_list, LogTags* tags,
95*598139dcSAndroid Build Coastguard Worker LogStatistics* stats)
96*598139dcSAndroid Build Coastguard Worker : reader_list_(reader_list), tags_(tags), stats_(stats) {
97*598139dcSAndroid Build Coastguard Worker Init();
98*598139dcSAndroid Build Coastguard Worker }
99*598139dcSAndroid Build Coastguard Worker
Init()100*598139dcSAndroid Build Coastguard Worker void SerializedLogBuffer::Init() {
101*598139dcSAndroid Build Coastguard Worker log_id_for_each(i) {
102*598139dcSAndroid Build Coastguard Worker if (!SetSize(i, GetBufferSizeFromProperties(i))) {
103*598139dcSAndroid Build Coastguard Worker SetSize(i, kLogBufferMinSize);
104*598139dcSAndroid Build Coastguard Worker }
105*598139dcSAndroid Build Coastguard Worker }
106*598139dcSAndroid Build Coastguard Worker
107*598139dcSAndroid Build Coastguard Worker // Release any sleeping reader threads to dump their current content.
108*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock};
109*598139dcSAndroid Build Coastguard Worker for (const auto& reader_thread : reader_list_->running_reader_threads()) {
110*598139dcSAndroid Build Coastguard Worker reader_thread->TriggerReader();
111*598139dcSAndroid Build Coastguard Worker }
112*598139dcSAndroid Build Coastguard Worker }
113*598139dcSAndroid Build Coastguard Worker
ShouldLog(log_id_t log_id,const char * msg,uint16_t len)114*598139dcSAndroid Build Coastguard Worker bool SerializedLogBuffer::ShouldLog(log_id_t log_id, const char* msg, uint16_t len) {
115*598139dcSAndroid Build Coastguard Worker if (log_id == LOG_ID_SECURITY) {
116*598139dcSAndroid Build Coastguard Worker return true;
117*598139dcSAndroid Build Coastguard Worker }
118*598139dcSAndroid Build Coastguard Worker
119*598139dcSAndroid Build Coastguard Worker int prio = ANDROID_LOG_INFO;
120*598139dcSAndroid Build Coastguard Worker const char* tag = nullptr;
121*598139dcSAndroid Build Coastguard Worker size_t tag_len = 0;
122*598139dcSAndroid Build Coastguard Worker if (IsBinary(log_id)) {
123*598139dcSAndroid Build Coastguard Worker int32_t tag_int = MsgToTag(msg, len);
124*598139dcSAndroid Build Coastguard Worker tag = tags_->tagToName(tag_int);
125*598139dcSAndroid Build Coastguard Worker if (tag) {
126*598139dcSAndroid Build Coastguard Worker tag_len = strlen(tag);
127*598139dcSAndroid Build Coastguard Worker }
128*598139dcSAndroid Build Coastguard Worker } else {
129*598139dcSAndroid Build Coastguard Worker prio = *msg;
130*598139dcSAndroid Build Coastguard Worker tag = msg + 1;
131*598139dcSAndroid Build Coastguard Worker tag_len = strnlen(tag, len - 1);
132*598139dcSAndroid Build Coastguard Worker }
133*598139dcSAndroid Build Coastguard Worker return __android_log_is_loggable_len(prio, tag, tag_len, ANDROID_LOG_VERBOSE);
134*598139dcSAndroid Build Coastguard Worker }
135*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)136*598139dcSAndroid Build Coastguard Worker int SerializedLogBuffer::Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
137*598139dcSAndroid Build Coastguard Worker const char* msg, uint16_t len) {
138*598139dcSAndroid Build Coastguard Worker if (!__android_log_id_is_valid(log_id) || len == 0) {
139*598139dcSAndroid Build Coastguard Worker return -EINVAL;
140*598139dcSAndroid Build Coastguard Worker }
141*598139dcSAndroid Build Coastguard Worker
142*598139dcSAndroid Build Coastguard Worker if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
143*598139dcSAndroid Build Coastguard Worker len = LOGGER_ENTRY_MAX_PAYLOAD;
144*598139dcSAndroid Build Coastguard Worker }
145*598139dcSAndroid Build Coastguard Worker
146*598139dcSAndroid Build Coastguard Worker if (!ShouldLog(log_id, msg, len)) {
147*598139dcSAndroid Build Coastguard Worker stats_->AddTotal(log_id, len);
148*598139dcSAndroid Build Coastguard Worker return -EACCES;
149*598139dcSAndroid Build Coastguard Worker }
150*598139dcSAndroid Build Coastguard Worker
151*598139dcSAndroid Build Coastguard Worker auto sequence = sequence_.fetch_add(1, std::memory_order_relaxed);
152*598139dcSAndroid Build Coastguard Worker
153*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock};
154*598139dcSAndroid Build Coastguard Worker auto entry = LogToLogBuffer(logs_[log_id], max_size_[log_id], sequence, realtime, uid, pid, tid,
155*598139dcSAndroid Build Coastguard Worker msg, len);
156*598139dcSAndroid Build Coastguard Worker stats_->Add(entry->ToLogStatisticsElement(log_id));
157*598139dcSAndroid Build Coastguard Worker
158*598139dcSAndroid Build Coastguard Worker MaybePrune(log_id);
159*598139dcSAndroid Build Coastguard Worker
160*598139dcSAndroid Build Coastguard Worker reader_list_->NotifyNewLog(1 << log_id);
161*598139dcSAndroid Build Coastguard Worker return len;
162*598139dcSAndroid Build Coastguard Worker }
163*598139dcSAndroid Build Coastguard Worker
MaybePrune(log_id_t log_id)164*598139dcSAndroid Build Coastguard Worker void SerializedLogBuffer::MaybePrune(log_id_t log_id) {
165*598139dcSAndroid Build Coastguard Worker size_t total_size = GetSizeUsed(log_id);
166*598139dcSAndroid Build Coastguard Worker size_t after_size = total_size;
167*598139dcSAndroid Build Coastguard Worker if (total_size > max_size_[log_id]) {
168*598139dcSAndroid Build Coastguard Worker Prune(log_id, total_size - max_size_[log_id]);
169*598139dcSAndroid Build Coastguard Worker after_size = GetSizeUsed(log_id);
170*598139dcSAndroid Build Coastguard Worker LOG(VERBOSE) << "Pruned Logs from log_id: " << log_id << ", previous size: " << total_size
171*598139dcSAndroid Build Coastguard Worker << " after size: " << after_size;
172*598139dcSAndroid Build Coastguard Worker }
173*598139dcSAndroid Build Coastguard Worker
174*598139dcSAndroid Build Coastguard Worker stats_->set_overhead(log_id, after_size);
175*598139dcSAndroid Build Coastguard Worker }
176*598139dcSAndroid Build Coastguard Worker
RemoveChunkFromStats(log_id_t log_id,SerializedLogChunk & chunk)177*598139dcSAndroid Build Coastguard Worker void SerializedLogBuffer::RemoveChunkFromStats(log_id_t log_id, SerializedLogChunk& chunk) {
178*598139dcSAndroid Build Coastguard Worker chunk.IncReaderRefCount();
179*598139dcSAndroid Build Coastguard Worker for (const auto& entry : chunk) {
180*598139dcSAndroid Build Coastguard Worker stats_->Subtract(entry.ToLogStatisticsElement(log_id));
181*598139dcSAndroid Build Coastguard Worker }
182*598139dcSAndroid Build Coastguard Worker chunk.DecReaderRefCount();
183*598139dcSAndroid Build Coastguard Worker }
184*598139dcSAndroid Build Coastguard Worker
Prune(log_id_t log_id,size_t bytes_to_free)185*598139dcSAndroid Build Coastguard Worker void SerializedLogBuffer::Prune(log_id_t log_id, size_t bytes_to_free) {
186*598139dcSAndroid Build Coastguard Worker auto& log_buffer = logs_[log_id];
187*598139dcSAndroid Build Coastguard Worker auto it = log_buffer.begin();
188*598139dcSAndroid Build Coastguard Worker while (it != log_buffer.end()) {
189*598139dcSAndroid Build Coastguard Worker for (const auto& reader_thread : reader_list_->running_reader_threads()) {
190*598139dcSAndroid Build Coastguard Worker if (!reader_thread->IsWatching(log_id)) {
191*598139dcSAndroid Build Coastguard Worker continue;
192*598139dcSAndroid Build Coastguard Worker }
193*598139dcSAndroid Build Coastguard Worker
194*598139dcSAndroid Build Coastguard Worker if (reader_thread->deadline().time_since_epoch().count() != 0) {
195*598139dcSAndroid Build Coastguard Worker // Always wake up wrapped readers when pruning. 'Wrapped' readers are an
196*598139dcSAndroid Build Coastguard Worker // optimization that allows the reader to wait until logs starting at a specified
197*598139dcSAndroid Build Coastguard Worker // time stamp are about to be pruned. This is error-prone however, since if that
198*598139dcSAndroid Build Coastguard Worker // timestamp is about to be pruned, the reader is not likely to read the messages
199*598139dcSAndroid Build Coastguard Worker // fast enough to not back-up logd. Instead, we can achieve an nearly-as-efficient
200*598139dcSAndroid Build Coastguard Worker // but not error-prune batching effect by waking the reader whenever any chunk is
201*598139dcSAndroid Build Coastguard Worker // about to be pruned.
202*598139dcSAndroid Build Coastguard Worker reader_thread->TriggerReader();
203*598139dcSAndroid Build Coastguard Worker }
204*598139dcSAndroid Build Coastguard Worker
205*598139dcSAndroid Build Coastguard Worker // Some readers may be still reading from this log chunk, log a warning that they are
206*598139dcSAndroid Build Coastguard Worker // about to lose logs.
207*598139dcSAndroid Build Coastguard Worker // TODO: We should forcefully disconnect the reader instead, such that the reader itself
208*598139dcSAndroid Build Coastguard Worker // has an indication that they've lost logs.
209*598139dcSAndroid Build Coastguard Worker if (reader_thread->start() <= it->highest_sequence_number()) {
210*598139dcSAndroid Build Coastguard Worker LOG(WARNING) << "Skipping entries from slow reader, " << reader_thread->name()
211*598139dcSAndroid Build Coastguard Worker << ", from LogBuffer::Prune()";
212*598139dcSAndroid Build Coastguard Worker }
213*598139dcSAndroid Build Coastguard Worker }
214*598139dcSAndroid Build Coastguard Worker
215*598139dcSAndroid Build Coastguard Worker // Increment ahead of time since we're going to erase this iterator from the list.
216*598139dcSAndroid Build Coastguard Worker auto it_to_prune = it++;
217*598139dcSAndroid Build Coastguard Worker
218*598139dcSAndroid Build Coastguard Worker // Readers may have a reference to the chunk to track their last read log_position.
219*598139dcSAndroid Build Coastguard Worker // Notify them to delete the reference.
220*598139dcSAndroid Build Coastguard Worker it_to_prune->NotifyReadersOfPrune(log_id);
221*598139dcSAndroid Build Coastguard Worker
222*598139dcSAndroid Build Coastguard Worker size_t buffer_size = it_to_prune->PruneSize();
223*598139dcSAndroid Build Coastguard Worker RemoveChunkFromStats(log_id, *it_to_prune);
224*598139dcSAndroid Build Coastguard Worker log_buffer.erase(it_to_prune);
225*598139dcSAndroid Build Coastguard Worker if (buffer_size >= bytes_to_free) {
226*598139dcSAndroid Build Coastguard Worker return;
227*598139dcSAndroid Build Coastguard Worker }
228*598139dcSAndroid Build Coastguard Worker bytes_to_free -= buffer_size;
229*598139dcSAndroid Build Coastguard Worker }
230*598139dcSAndroid Build Coastguard Worker }
231*598139dcSAndroid Build Coastguard Worker
UidClear(log_id_t log_id,uid_t uid)232*598139dcSAndroid Build Coastguard Worker void SerializedLogBuffer::UidClear(log_id_t log_id, uid_t uid) {
233*598139dcSAndroid Build Coastguard Worker // Wake all readers; see comment in Prune().
234*598139dcSAndroid Build Coastguard Worker for (const auto& reader_thread : reader_list_->running_reader_threads()) {
235*598139dcSAndroid Build Coastguard Worker if (!reader_thread->IsWatching(log_id)) {
236*598139dcSAndroid Build Coastguard Worker continue;
237*598139dcSAndroid Build Coastguard Worker }
238*598139dcSAndroid Build Coastguard Worker
239*598139dcSAndroid Build Coastguard Worker if (reader_thread->deadline().time_since_epoch().count() != 0) {
240*598139dcSAndroid Build Coastguard Worker reader_thread->TriggerReader();
241*598139dcSAndroid Build Coastguard Worker }
242*598139dcSAndroid Build Coastguard Worker }
243*598139dcSAndroid Build Coastguard Worker ClearLogsByUid(logs_[log_id], uid, max_size_[log_id], log_id, stats_);
244*598139dcSAndroid Build Coastguard Worker }
245*598139dcSAndroid Build Coastguard Worker
CreateFlushToState(uint64_t start,LogMask log_mask)246*598139dcSAndroid Build Coastguard Worker std::unique_ptr<FlushToState> SerializedLogBuffer::CreateFlushToState(uint64_t start,
247*598139dcSAndroid Build Coastguard Worker LogMask log_mask) {
248*598139dcSAndroid Build Coastguard Worker return std::make_unique<SerializedFlushToState>(start, log_mask, logs_);
249*598139dcSAndroid Build Coastguard Worker }
250*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)251*598139dcSAndroid Build Coastguard Worker bool SerializedLogBuffer::FlushTo(
252*598139dcSAndroid Build Coastguard Worker LogWriter* writer, FlushToState& abstract_state,
253*598139dcSAndroid Build Coastguard Worker const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
254*598139dcSAndroid Build Coastguard Worker log_time realtime)>& filter) {
255*598139dcSAndroid Build Coastguard Worker auto& state = reinterpret_cast<SerializedFlushToState&>(abstract_state);
256*598139dcSAndroid Build Coastguard Worker
257*598139dcSAndroid Build Coastguard Worker while (state.HasUnreadLogs()) {
258*598139dcSAndroid Build Coastguard Worker LogWithId top = state.PopNextUnreadLog();
259*598139dcSAndroid Build Coastguard Worker auto* entry = top.entry;
260*598139dcSAndroid Build Coastguard Worker auto log_id = top.log_id;
261*598139dcSAndroid Build Coastguard Worker
262*598139dcSAndroid Build Coastguard Worker if (entry->sequence() < state.start()) {
263*598139dcSAndroid Build Coastguard Worker continue;
264*598139dcSAndroid Build Coastguard Worker }
265*598139dcSAndroid Build Coastguard Worker state.set_start(entry->sequence());
266*598139dcSAndroid Build Coastguard Worker
267*598139dcSAndroid Build Coastguard Worker if (!writer->privileged() && entry->uid() != writer->uid()) {
268*598139dcSAndroid Build Coastguard Worker continue;
269*598139dcSAndroid Build Coastguard Worker }
270*598139dcSAndroid Build Coastguard Worker
271*598139dcSAndroid Build Coastguard Worker if (filter) {
272*598139dcSAndroid Build Coastguard Worker auto ret = filter(log_id, entry->pid(), entry->sequence(), entry->realtime());
273*598139dcSAndroid Build Coastguard Worker if (ret == FilterResult::kSkip) {
274*598139dcSAndroid Build Coastguard Worker continue;
275*598139dcSAndroid Build Coastguard Worker }
276*598139dcSAndroid Build Coastguard Worker if (ret == FilterResult::kStop) {
277*598139dcSAndroid Build Coastguard Worker break;
278*598139dcSAndroid Build Coastguard Worker }
279*598139dcSAndroid Build Coastguard Worker }
280*598139dcSAndroid Build Coastguard Worker
281*598139dcSAndroid Build Coastguard Worker // We copy the log entry such that we can flush it without the lock. We never block pruning
282*598139dcSAndroid Build Coastguard Worker // waiting for this Flush() to complete.
283*598139dcSAndroid Build Coastguard Worker constexpr size_t kMaxEntrySize = sizeof(*entry) + LOGGER_ENTRY_MAX_PAYLOAD + 1;
284*598139dcSAndroid Build Coastguard Worker unsigned char entry_copy[kMaxEntrySize] __attribute__((uninitialized));
285*598139dcSAndroid Build Coastguard Worker CHECK_LT(entry->msg_len(), LOGGER_ENTRY_MAX_PAYLOAD + 1);
286*598139dcSAndroid Build Coastguard Worker memcpy(entry_copy, entry, sizeof(*entry) + entry->msg_len());
287*598139dcSAndroid Build Coastguard Worker logd_lock.unlock();
288*598139dcSAndroid Build Coastguard Worker
289*598139dcSAndroid Build Coastguard Worker if (!reinterpret_cast<SerializedLogEntry*>(entry_copy)->Flush(writer, log_id)) {
290*598139dcSAndroid Build Coastguard Worker logd_lock.lock();
291*598139dcSAndroid Build Coastguard Worker return false;
292*598139dcSAndroid Build Coastguard Worker }
293*598139dcSAndroid Build Coastguard Worker
294*598139dcSAndroid Build Coastguard Worker logd_lock.lock();
295*598139dcSAndroid Build Coastguard Worker }
296*598139dcSAndroid Build Coastguard Worker
297*598139dcSAndroid Build Coastguard Worker state.set_start(state.start() + 1);
298*598139dcSAndroid Build Coastguard Worker return true;
299*598139dcSAndroid Build Coastguard Worker }
300*598139dcSAndroid Build Coastguard Worker
Clear(log_id_t id,uid_t uid)301*598139dcSAndroid Build Coastguard Worker bool SerializedLogBuffer::Clear(log_id_t id, uid_t uid) {
302*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock};
303*598139dcSAndroid Build Coastguard Worker if (uid == 0) {
304*598139dcSAndroid Build Coastguard Worker Prune(id, ULONG_MAX);
305*598139dcSAndroid Build Coastguard Worker } else {
306*598139dcSAndroid Build Coastguard Worker UidClear(id, uid);
307*598139dcSAndroid Build Coastguard Worker }
308*598139dcSAndroid Build Coastguard Worker
309*598139dcSAndroid Build Coastguard Worker // Clearing SerializedLogBuffer never waits for readers and therefore is always successful.
310*598139dcSAndroid Build Coastguard Worker return true;
311*598139dcSAndroid Build Coastguard Worker }
312*598139dcSAndroid Build Coastguard Worker
GetSizeUsed(log_id_t id)313*598139dcSAndroid Build Coastguard Worker size_t SerializedLogBuffer::GetSizeUsed(log_id_t id) {
314*598139dcSAndroid Build Coastguard Worker size_t total_size = 0;
315*598139dcSAndroid Build Coastguard Worker for (const auto& chunk : logs_[id]) {
316*598139dcSAndroid Build Coastguard Worker total_size += chunk.PruneSize();
317*598139dcSAndroid Build Coastguard Worker }
318*598139dcSAndroid Build Coastguard Worker return total_size;
319*598139dcSAndroid Build Coastguard Worker }
320*598139dcSAndroid Build Coastguard Worker
GetSize(log_id_t id)321*598139dcSAndroid Build Coastguard Worker size_t SerializedLogBuffer::GetSize(log_id_t id) {
322*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock};
323*598139dcSAndroid Build Coastguard Worker return max_size_[id];
324*598139dcSAndroid Build Coastguard Worker }
325*598139dcSAndroid Build Coastguard Worker
326*598139dcSAndroid Build Coastguard Worker // New SerializedLogChunk objects will be allocated according to the new size, but older one are
327*598139dcSAndroid Build Coastguard Worker // unchanged. MaybePrune() is called on the log buffer to reduce it to an appropriate size if the
328*598139dcSAndroid Build Coastguard Worker // new size is lower.
SetSize(log_id_t id,size_t size)329*598139dcSAndroid Build Coastguard Worker bool SerializedLogBuffer::SetSize(log_id_t id, size_t size) {
330*598139dcSAndroid Build Coastguard Worker // Reasonable limits ...
331*598139dcSAndroid Build Coastguard Worker if (!IsValidBufferSize(size)) {
332*598139dcSAndroid Build Coastguard Worker return false;
333*598139dcSAndroid Build Coastguard Worker }
334*598139dcSAndroid Build Coastguard Worker
335*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock};
336*598139dcSAndroid Build Coastguard Worker max_size_[id] = size;
337*598139dcSAndroid Build Coastguard Worker
338*598139dcSAndroid Build Coastguard Worker MaybePrune(id);
339*598139dcSAndroid Build Coastguard Worker
340*598139dcSAndroid Build Coastguard Worker return true;
341*598139dcSAndroid Build Coastguard Worker }
342