blob: 5b9beab50eabc14e397c802c4c943a89c31dd3b9 [file] [log] [blame]
Mark Salyzynd774bce2014-02-06 14:48:50 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tom Cherry4011d5a2020-05-07 09:13:12 -070017#pragma once
Mark Salyzynd774bce2014-02-06 14:48:50 -080018
Mark Salyzyn7739a272016-12-19 14:51:15 -080019#include <ctype.h>
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -070020#include <inttypes.h>
21#include <stdint.h>
Mark Salyzyn1435b472015-03-16 08:26:05 -070022#include <stdlib.h>
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -070023#include <string.h>
Mark Salyzynd774bce2014-02-06 14:48:50 -080024#include <sys/types.h>
25
Mark Salyzyn65059532017-03-10 14:31:54 -080026#include <algorithm> // std::max
Tom Cherry4011d5a2020-05-07 09:13:12 -070027#include <array>
Mark Salyzyn7739a272016-12-19 14:51:15 -080028#include <memory>
Tom Cherry479b5032020-05-07 14:44:43 -070029#include <mutex>
Elliott Hughes3d37a962017-11-30 16:31:35 -080030#include <string>
31#include <string_view>
Mark Salyzyn6a404192015-05-19 09:12:30 -070032#include <unordered_map>
33
Elliott Hughes0a7adf02015-12-04 22:00:26 -080034#include <android-base/stringprintf.h>
Tom Cherry479b5032020-05-07 14:44:43 -070035#include <android-base/thread_annotations.h>
Mark Salyzyn65059532017-03-10 14:31:54 -080036#include <android/log.h>
Mark Salyzynda924cb2017-04-14 09:46:57 -070037#include <log/log_time.h>
Mark Salyzyn1761a842015-08-21 16:44:30 -070038#include <private/android_filesystem_config.h>
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -070039#include <utils/FastStrcmp.h>
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070040
Mark Salyzyn7c7c39a2015-08-28 08:02:59 -070041#include "LogUtils.h"
Mark Salyzynd774bce2014-02-06 14:48:50 -080042
43#define log_id_for_each(i) \
Mark Salyzyn65059532017-03-10 14:31:54 -080044 for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1))
Mark Salyzynd774bce2014-02-06 14:48:50 -080045
Mark Salyzyn1761a842015-08-21 16:44:30 -070046class LogStatistics;
Tom Cherryc5b802c2020-06-03 13:49:24 -070047class UidEntry;
48class PidEntry;
Mark Salyzyn1761a842015-08-21 16:44:30 -070049
Tom Cherry8f459112020-06-02 15:39:21 -070050struct LogStatisticsElement {
51 uid_t uid;
52 pid_t pid;
53 pid_t tid;
54 uint32_t tag;
55 log_time realtime;
56 const char* msg;
57 uint16_t msg_len;
Tom Cherry8f459112020-06-02 15:39:21 -070058 log_id_t log_id;
Tom Cherrya3d6aa62020-06-19 12:21:21 -070059 uint16_t total_len;
Tom Cherry8f459112020-06-02 15:39:21 -070060};
61
Mark Salyzyn1435b472015-03-16 08:26:05 -070062template <typename TKey, typename TEntry>
Mark Salyzyn6a404192015-05-19 09:12:30 -070063class LogHashtable {
Mark Salyzyn6a404192015-05-19 09:12:30 -070064 std::unordered_map<TKey, TEntry> map;
65
Mark Salyzyn17e72122016-10-06 09:55:21 -070066 size_t bucket_size() const {
67 size_t count = 0;
68 for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
69 size_t bucket_size = map.bucket_size(idx);
70 if (bucket_size == 0) bucket_size = 1;
71 count += bucket_size;
72 }
73 float load_factor = map.max_load_factor();
74 if (load_factor < 1.0) return count;
75 return count * load_factor;
76 }
77
78 static const size_t unordered_map_per_entry_overhead = sizeof(void*);
79 static const size_t unordered_map_bucket_overhead = sizeof(void*);
80
Tom Cherryf1910142020-05-19 19:01:16 -070081 public:
Mark Salyzyn65059532017-03-10 14:31:54 -080082 size_t size() const {
83 return map.size();
84 }
Mark Salyzynb6c5c872016-10-06 10:09:24 -070085
Mark Salyzyn17e72122016-10-06 09:55:21 -070086 // Estimate unordered_map memory usage.
87 size_t sizeOf() const {
88 return sizeof(*this) +
Mark Salyzynb6c5c872016-10-06 10:09:24 -070089 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn17e72122016-10-06 09:55:21 -070090 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
91 }
92
Mark Salyzyn6a404192015-05-19 09:12:30 -070093 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn65059532017-03-10 14:31:54 -080094 typedef
95 typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn6a404192015-05-19 09:12:30 -070096
Tom Cherry4011d5a2020-05-07 09:13:12 -070097 // Returns a sorted array of up to len highest entries sorted by size. If fewer than len
98 // entries are found, their positions are set to nullptr.
99 template <size_t len>
Tom Cherryc5b802c2020-06-03 13:49:24 -0700100 void MaxEntries(uid_t uid, pid_t pid, std::array<const TKey*, len>& out_keys,
101 std::array<const TEntry*, len>& out_entries) const {
102 out_keys.fill(nullptr);
103 out_entries.fill(nullptr);
104 for (const auto& [key, entry] : map) {
105 uid_t entry_uid = 0;
106 if constexpr (std::is_same_v<TEntry, UidEntry>) {
107 entry_uid = key;
108 } else {
109 entry_uid = entry.uid();
110 }
111 if (uid != AID_ROOT && uid != entry_uid) {
Mark Salyzyn4a2fc1c2015-12-17 09:58:43 -0800112 continue;
113 }
Tom Cherryc5b802c2020-06-03 13:49:24 -0700114 pid_t entry_pid = 0;
115 if constexpr (std::is_same_v<TEntry, PidEntry>) {
116 entry_pid = key;
117 } else {
118 entry_pid = entry.pid();
119 }
120 if (pid && entry_pid && pid != entry_pid) {
Mark Salyzyn4a2fc1c2015-12-17 09:58:43 -0800121 continue;
122 }
123
Mark Salyzyn1761a842015-08-21 16:44:30 -0700124 size_t sizes = entry.getSizes();
125 ssize_t index = len - 1;
Tom Cherryc5b802c2020-06-03 13:49:24 -0700126 while ((!out_entries[index] || sizes > out_entries[index]->getSizes()) && --index >= 0)
Mark Salyzyn1435b472015-03-16 08:26:05 -0700127 ;
Mark Salyzyn1761a842015-08-21 16:44:30 -0700128 if (++index < (ssize_t)len) {
129 size_t num = len - index - 1;
130 if (num) {
Tom Cherry17b77582020-06-17 11:40:55 -0700131 memmove(&out_keys[index + 1], &out_keys[index], num * sizeof(const TKey*));
Tom Cherryc5b802c2020-06-03 13:49:24 -0700132 memmove(&out_entries[index + 1], &out_entries[index],
Tom Cherry17b77582020-06-17 11:40:55 -0700133 num * sizeof(const TEntry*));
Mark Salyzyn1435b472015-03-16 08:26:05 -0700134 }
Tom Cherryc5b802c2020-06-03 13:49:24 -0700135 out_keys[index] = &key;
136 out_entries[index] = &entry;
Mark Salyzyn1435b472015-03-16 08:26:05 -0700137 }
138 }
Mark Salyzyn1435b472015-03-16 08:26:05 -0700139 }
140
Tom Cherry8f459112020-06-02 15:39:21 -0700141 iterator Add(const TKey& key, const LogStatisticsElement& element) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700142 iterator it = map.find(key);
143 if (it == map.end()) {
Mark Salyzyn1761a842015-08-21 16:44:30 -0700144 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn6a404192015-05-19 09:12:30 -0700145 } else {
Tom Cherryf1910142020-05-19 19:01:16 -0700146 it->second.Add(element);
Mark Salyzyn6a404192015-05-19 09:12:30 -0700147 }
148 return it;
Mark Salyzyn1435b472015-03-16 08:26:05 -0700149 }
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700150
Tom Cherryf1910142020-05-19 19:01:16 -0700151 iterator Add(const TKey& key) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700152 iterator it = map.find(key);
153 if (it == map.end()) {
154 it = map.insert(std::make_pair(key, TEntry(key))).first;
155 } else {
Tom Cherryf1910142020-05-19 19:01:16 -0700156 it->second.Add(key);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700157 }
Mark Salyzyn6a404192015-05-19 09:12:30 -0700158 return it;
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700159 }
160
Tom Cherry8f459112020-06-02 15:39:21 -0700161 void Subtract(const TKey& key, const LogStatisticsElement& element) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700162 iterator it = map.find(key);
Tom Cherryf1910142020-05-19 19:01:16 -0700163 if (it != map.end() && it->second.Subtract(element)) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700164 map.erase(it);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700165 }
166 }
167
Tom Cherry8f459112020-06-02 15:39:21 -0700168 void Drop(const TKey& key, const LogStatisticsElement& element) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700169 iterator it = map.find(key);
170 if (it != map.end()) {
Tom Cherryf1910142020-05-19 19:01:16 -0700171 it->second.Drop(element);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700172 }
173 }
174
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700175 void Erase(const TKey& key, const LogStatisticsElement& element) {
176 iterator it = map.find(key);
177 if (it != map.end()) {
178 it->second.Erase(element);
179 }
180 }
181
Tom Cherryf1910142020-05-19 19:01:16 -0700182 iterator begin() { return map.begin(); }
183 const_iterator begin() const { return map.begin(); }
184 iterator end() { return map.end(); }
185 const_iterator end() const { return map.end(); }
Mark Salyzyn1435b472015-03-16 08:26:05 -0700186};
187
Tom Cherryf1910142020-05-19 19:01:16 -0700188class EntryBase {
189 public:
190 EntryBase() : size_(0) {}
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700191 explicit EntryBase(const LogStatisticsElement& element) : size_(element.total_len) {}
Mark Salyzyn1761a842015-08-21 16:44:30 -0700192
Tom Cherryf1910142020-05-19 19:01:16 -0700193 size_t getSizes() const { return size_; }
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700194
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700195 void Add(const LogStatisticsElement& element) { size_ += element.total_len; }
Tom Cherry8f459112020-06-02 15:39:21 -0700196 bool Subtract(const LogStatisticsElement& element) {
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700197 size_ -= element.total_len;
198 return size_ == 0;
Mark Salyzyn65059532017-03-10 14:31:54 -0800199 }
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700200 void Drop(const LogStatisticsElement& element) { size_ -= element.msg_len; }
201 void Erase(const LogStatisticsElement& element) { size_ -= element.total_len; }
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700202
Tom Cherryf1910142020-05-19 19:01:16 -0700203 static constexpr size_t PRUNED_LEN = 14;
204 static constexpr size_t TOTAL_LEN = 80;
Mark Salyzyn1761a842015-08-21 16:44:30 -0700205
Mark Salyzyn65059532017-03-10 14:31:54 -0800206 static std::string formatLine(const std::string& name,
207 const std::string& size,
208 const std::string& pruned) {
Tom Cherryf1910142020-05-19 19:01:16 -0700209 ssize_t drop_len = std::max(pruned.length() + 1, PRUNED_LEN);
210 ssize_t size_len = std::max(size.length() + 1, TOTAL_LEN - name.length() - drop_len - 1);
Mark Salyzyn1761a842015-08-21 16:44:30 -0700211
Mark Salyzyn65059532017-03-10 14:31:54 -0800212 std::string ret = android::base::StringPrintf(
213 "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
214 (int)drop_len, pruned.c_str());
Mark Salyzyn7739a272016-12-19 14:51:15 -0800215 // remove any trailing spaces
216 size_t pos = ret.size();
217 size_t len = 0;
218 while (pos && isspace(ret[--pos])) ++len;
219 if (len) ret.erase(pos + 1, len);
220 return ret + "\n";
Mark Salyzyn1761a842015-08-21 16:44:30 -0700221 }
Tom Cherryf1910142020-05-19 19:01:16 -0700222
223 private:
224 size_t size_;
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700225};
226
Elliott Hughes225e5c62022-09-16 23:01:59 +0000227class UidEntry : public EntryBase {
Tom Cherryf1910142020-05-19 19:01:16 -0700228 public:
Tom Cherry8f459112020-06-02 15:39:21 -0700229 explicit UidEntry(const LogStatisticsElement& element)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000230 : EntryBase(element), pid_(element.pid) {}
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700231
Tom Cherryf1910142020-05-19 19:01:16 -0700232 pid_t pid() const { return pid_; }
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700233
Tom Cherry8f459112020-06-02 15:39:21 -0700234 void Add(const LogStatisticsElement& element) {
235 if (pid_ != element.pid) {
Tom Cherryf1910142020-05-19 19:01:16 -0700236 pid_ = -1;
Mark Salyzyn4a2fc1c2015-12-17 09:58:43 -0800237 }
Elliott Hughes225e5c62022-09-16 23:01:59 +0000238 EntryBase::Add(element);
Mark Salyzyn4a2fc1c2015-12-17 09:58:43 -0800239 }
Mark Salyzyn1761a842015-08-21 16:44:30 -0700240
Mark Salyzyn65059532017-03-10 14:31:54 -0800241 std::string formatHeader(const std::string& name, log_id_t id) const;
Tom Cherryc5b802c2020-06-03 13:49:24 -0700242 std::string format(const LogStatistics& stat, log_id_t id, uid_t uid) const;
Tom Cherryf1910142020-05-19 19:01:16 -0700243
244 private:
Tom Cherryf1910142020-05-19 19:01:16 -0700245 pid_t pid_;
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700246};
247
Tom Cherryd96d26a2019-06-28 13:21:27 -0700248namespace android {
249uid_t pidToUid(pid_t pid);
250}
251
Elliott Hughes225e5c62022-09-16 23:01:59 +0000252class PidEntry : public EntryBase {
Tom Cherryf1910142020-05-19 19:01:16 -0700253 public:
Mark Salyzyn65059532017-03-10 14:31:54 -0800254 explicit PidEntry(pid_t pid)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000255 : EntryBase(), uid_(android::pidToUid(pid)), name_(android::pidToName(pid)) {}
Tom Cherry8f459112020-06-02 15:39:21 -0700256 explicit PidEntry(const LogStatisticsElement& element)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000257 : EntryBase(element), uid_(element.uid), name_(android::pidToName(element.pid)) {}
Mark Salyzyn65059532017-03-10 14:31:54 -0800258 PidEntry(const PidEntry& element)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000259 : EntryBase(element),
Tom Cherryf1910142020-05-19 19:01:16 -0700260 uid_(element.uid_),
261 name_(element.name_ ? strdup(element.name_) : nullptr) {}
262 ~PidEntry() { free(name_); }
Mark Salyzyn1435b472015-03-16 08:26:05 -0700263
Tom Cherryf1910142020-05-19 19:01:16 -0700264 uid_t uid() const { return uid_; }
265 const char* name() const { return name_; }
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700266
Tom Cherryf1910142020-05-19 19:01:16 -0700267 void Add(pid_t new_pid) {
268 if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
269 free(name_);
270 name_ = nullptr;
Mark Salyzyn8cca8252015-04-20 10:27:38 -0700271 }
Tom Cherryf1910142020-05-19 19:01:16 -0700272 if (!name_) {
273 name_ = android::pidToName(new_pid);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700274 }
275 }
276
Tom Cherry8f459112020-06-02 15:39:21 -0700277 void Add(const LogStatisticsElement& element) {
278 uid_t incoming_uid = element.uid;
Tom Cherryf1910142020-05-19 19:01:16 -0700279 if (uid() != incoming_uid) {
280 uid_ = incoming_uid;
281 free(name_);
Tom Cherry8f459112020-06-02 15:39:21 -0700282 name_ = android::pidToName(element.pid);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700283 } else {
Tom Cherry8f459112020-06-02 15:39:21 -0700284 Add(element.pid);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700285 }
Elliott Hughes225e5c62022-09-16 23:01:59 +0000286 EntryBase::Add(element);
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700287 }
Mark Salyzyn1761a842015-08-21 16:44:30 -0700288
Mark Salyzyn65059532017-03-10 14:31:54 -0800289 std::string formatHeader(const std::string& name, log_id_t id) const;
Tom Cherryc5b802c2020-06-03 13:49:24 -0700290 std::string format(const LogStatistics& stat, log_id_t id, pid_t pid) const;
Tom Cherryf1910142020-05-19 19:01:16 -0700291
292 private:
Tom Cherryf1910142020-05-19 19:01:16 -0700293 uid_t uid_;
294 char* name_;
Mark Salyzynf96ac902015-04-13 14:24:45 -0700295};
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700296
Elliott Hughes225e5c62022-09-16 23:01:59 +0000297class TidEntry : public EntryBase {
Tom Cherryf1910142020-05-19 19:01:16 -0700298 public:
Mark Salyzyn65059532017-03-10 14:31:54 -0800299 TidEntry(pid_t tid, pid_t pid)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000300 : EntryBase(), pid_(pid), uid_(android::pidToUid(tid)), name_(android::tidToName(tid)) {}
Tom Cherry8f459112020-06-02 15:39:21 -0700301 explicit TidEntry(const LogStatisticsElement& element)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000302 : EntryBase(element),
Tom Cherry8f459112020-06-02 15:39:21 -0700303 pid_(element.pid),
304 uid_(element.uid),
Tom Cherryc5b802c2020-06-03 13:49:24 -0700305 name_(android::tidToName(element.tid)) {}
Mark Salyzyn65059532017-03-10 14:31:54 -0800306 TidEntry(const TidEntry& element)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000307 : EntryBase(element),
Tom Cherryf1910142020-05-19 19:01:16 -0700308 pid_(element.pid_),
309 uid_(element.uid_),
310 name_(element.name_ ? strdup(element.name_) : nullptr) {}
311 ~TidEntry() { free(name_); }
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700312
Tom Cherryf1910142020-05-19 19:01:16 -0700313 pid_t pid() const { return pid_; }
314 uid_t uid() const { return uid_; }
315 const char* name() const { return name_; }
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700316
Tom Cherryf1910142020-05-19 19:01:16 -0700317 void Add(pid_t incomingTid) {
318 if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
319 free(name_);
320 name_ = nullptr;
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700321 }
Tom Cherryf1910142020-05-19 19:01:16 -0700322 if (!name_) {
323 name_ = android::tidToName(incomingTid);
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700324 }
325 }
326
Tom Cherry8f459112020-06-02 15:39:21 -0700327 void Add(const LogStatisticsElement& element) {
328 uid_t incoming_uid = element.uid;
329 pid_t incoming_pid = element.pid;
Tom Cherryf1910142020-05-19 19:01:16 -0700330 if (uid() != incoming_uid || pid() != incoming_pid) {
331 uid_ = incoming_uid;
332 pid_ = incoming_pid;
333 free(name_);
Tom Cherry8f459112020-06-02 15:39:21 -0700334 name_ = android::tidToName(element.tid);
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700335 } else {
Tom Cherry8f459112020-06-02 15:39:21 -0700336 Add(element.tid);
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700337 }
Elliott Hughes225e5c62022-09-16 23:01:59 +0000338 EntryBase::Add(element);
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700339 }
Mark Salyzyn1761a842015-08-21 16:44:30 -0700340
Mark Salyzyn65059532017-03-10 14:31:54 -0800341 std::string formatHeader(const std::string& name, log_id_t id) const;
Tom Cherryc5b802c2020-06-03 13:49:24 -0700342 std::string format(const LogStatistics& stat, log_id_t id, pid_t pid) const;
Tom Cherryf1910142020-05-19 19:01:16 -0700343
344 private:
Tom Cherryf1910142020-05-19 19:01:16 -0700345 pid_t pid_;
346 uid_t uid_;
347 char* name_;
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700348};
349
Elliott Hughes225e5c62022-09-16 23:01:59 +0000350class TagEntry : public EntryBase {
Tom Cherryf1910142020-05-19 19:01:16 -0700351 public:
Tom Cherry8f459112020-06-02 15:39:21 -0700352 explicit TagEntry(const LogStatisticsElement& element)
Elliott Hughes225e5c62022-09-16 23:01:59 +0000353 : EntryBase(element), tag_(element.tag), pid_(element.pid), uid_(element.uid) {}
Mark Salyzynf96ac902015-04-13 14:24:45 -0700354
Tom Cherryf1910142020-05-19 19:01:16 -0700355 uint32_t key() const { return tag_; }
356 pid_t pid() const { return pid_; }
357 uid_t uid() const { return uid_; }
358 const char* name() const { return android::tagToName(tag_); }
Mark Salyzynf96ac902015-04-13 14:24:45 -0700359
Tom Cherry8f459112020-06-02 15:39:21 -0700360 void Add(const LogStatisticsElement& element) {
361 if (uid_ != element.uid) {
Tom Cherryf1910142020-05-19 19:01:16 -0700362 uid_ = -1;
Mark Salyzynf96ac902015-04-13 14:24:45 -0700363 }
Tom Cherry8f459112020-06-02 15:39:21 -0700364 if (pid_ != element.pid) {
Tom Cherryf1910142020-05-19 19:01:16 -0700365 pid_ = -1;
Mark Salyzyn4a2fc1c2015-12-17 09:58:43 -0800366 }
Elliott Hughes225e5c62022-09-16 23:01:59 +0000367 EntryBase::Add(element);
Mark Salyzynf96ac902015-04-13 14:24:45 -0700368 }
Mark Salyzyn1761a842015-08-21 16:44:30 -0700369
Mark Salyzyn65059532017-03-10 14:31:54 -0800370 std::string formatHeader(const std::string& name, log_id_t id) const;
Tom Cherryc5b802c2020-06-03 13:49:24 -0700371 std::string format(const LogStatistics& stat, log_id_t id, uint32_t) const;
Tom Cherryf1910142020-05-19 19:01:16 -0700372
373 private:
374 const uint32_t tag_;
375 pid_t pid_;
376 uid_t uid_;
Mark Salyzyn1435b472015-03-16 08:26:05 -0700377};
378
Tom Cherryf1910142020-05-19 19:01:16 -0700379class TagNameEntry : public EntryBase {
380 public:
Tom Cherry8f459112020-06-02 15:39:21 -0700381 explicit TagNameEntry(const LogStatisticsElement& element)
Tom Cherryc5b802c2020-06-03 13:49:24 -0700382 : EntryBase(element), tid_(element.tid), pid_(element.pid), uid_(element.uid) {}
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700383
Tom Cherryf1910142020-05-19 19:01:16 -0700384 pid_t tid() const { return tid_; }
385 pid_t pid() const { return pid_; }
386 uid_t uid() const { return uid_; }
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700387
Tom Cherry8f459112020-06-02 15:39:21 -0700388 void Add(const LogStatisticsElement& element) {
389 if (uid_ != element.uid) {
Tom Cherryf1910142020-05-19 19:01:16 -0700390 uid_ = -1;
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700391 }
Tom Cherry8f459112020-06-02 15:39:21 -0700392 if (pid_ != element.pid) {
Tom Cherryf1910142020-05-19 19:01:16 -0700393 pid_ = -1;
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700394 }
Tom Cherry8f459112020-06-02 15:39:21 -0700395 if (tid_ != element.tid) {
Tom Cherryf1910142020-05-19 19:01:16 -0700396 tid_ = -1;
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700397 }
Tom Cherryf1910142020-05-19 19:01:16 -0700398 EntryBase::Add(element);
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700399 }
400
401 std::string formatHeader(const std::string& name, log_id_t id) const;
Tom Cherry8a34ac42020-06-03 15:38:32 -0700402 std::string format(const LogStatistics& stat, log_id_t id, const std::string& key_name) const;
Tom Cherryf1910142020-05-19 19:01:16 -0700403
404 private:
405 pid_t tid_;
406 pid_t pid_;
407 uid_t uid_;
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700408};
409
Mark Salyzynd774bce2014-02-06 14:48:50 -0800410class LogStatistics {
Mark Salyzynb986afa2015-08-24 11:08:00 -0700411 friend UidEntry;
Tom Cherry479b5032020-05-07 14:44:43 -0700412 friend PidEntry;
413 friend TidEntry;
Mark Salyzynb986afa2015-08-24 11:08:00 -0700414
Tom Cherry479b5032020-05-07 14:44:43 -0700415 size_t mSizes[LOG_ID_MAX] GUARDED_BY(lock_);
416 size_t mElements[LOG_ID_MAX] GUARDED_BY(lock_);
Tom Cherry479b5032020-05-07 14:44:43 -0700417 size_t mSizesTotal[LOG_ID_MAX] GUARDED_BY(lock_);
418 size_t mElementsTotal[LOG_ID_MAX] GUARDED_BY(lock_);
419 log_time mOldest[LOG_ID_MAX] GUARDED_BY(lock_);
420 log_time mNewest[LOG_ID_MAX] GUARDED_BY(lock_);
Tom Cherry479b5032020-05-07 14:44:43 -0700421 static std::atomic<size_t> SizesTotal;
Mark Salyzyn1435b472015-03-16 08:26:05 -0700422 bool enable;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800423
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700424 // uid to size list
Mark Salyzyn1435b472015-03-16 08:26:05 -0700425 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Tom Cherry479b5032020-05-07 14:44:43 -0700426 uidTable_t uidTable[LOG_ID_MAX] GUARDED_BY(lock_);
Mark Salyzynfe639a02014-02-19 17:18:31 -0800427
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700428 // pid of system to size list
429 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
Tom Cherry479b5032020-05-07 14:44:43 -0700430 pidSystemTable_t pidSystemTable[LOG_ID_MAX] GUARDED_BY(lock_);
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700431
Mark Salyzyn1435b472015-03-16 08:26:05 -0700432 // pid to uid list
433 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
Tom Cherry479b5032020-05-07 14:44:43 -0700434 pidTable_t pidTable GUARDED_BY(lock_);
Mark Salyzyn1435b472015-03-16 08:26:05 -0700435
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700436 // tid to uid list
437 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
Tom Cherry479b5032020-05-07 14:44:43 -0700438 tidTable_t tidTable GUARDED_BY(lock_);
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700439
Mark Salyzynf96ac902015-04-13 14:24:45 -0700440 // tag list
441 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
Tom Cherry479b5032020-05-07 14:44:43 -0700442 tagTable_t tagTable GUARDED_BY(lock_);
Mark Salyzynf96ac902015-04-13 14:24:45 -0700443
Mark Salyzync9690862015-12-04 10:59:45 -0800444 // security tag list
Tom Cherry479b5032020-05-07 14:44:43 -0700445 tagTable_t securityTagTable GUARDED_BY(lock_);
Mark Salyzync9690862015-12-04 10:59:45 -0800446
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700447 // global tag list
Tom Cherry8a34ac42020-06-03 15:38:32 -0700448 typedef LogHashtable<std::string, TagNameEntry> tagNameTable_t;
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700449 tagNameTable_t tagNameTable;
450
Tom Cherry479b5032020-05-07 14:44:43 -0700451 size_t sizeOf() const REQUIRES(lock_) {
Mark Salyzyn17e72122016-10-06 09:55:21 -0700452 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb6c5c872016-10-06 10:09:24 -0700453 tagTable.sizeOf() + securityTagTable.sizeOf() +
Mark Salyzyn9a8c5f52017-04-19 14:39:21 -0700454 tagNameTable.sizeOf() +
Mark Salyzynb6c5c872016-10-06 10:09:24 -0700455 (pidTable.size() * sizeof(pidTable_t::iterator)) +
456 (tagTable.size() * sizeof(tagTable_t::iterator));
Tom Cherry17b77582020-06-17 11:40:55 -0700457 for (const auto& it : pidTable) {
Tom Cherryf1910142020-05-19 19:01:16 -0700458 const char* name = it.second.name();
Mark Salyzyn17e72122016-10-06 09:55:21 -0700459 if (name) size += strlen(name) + 1;
460 }
Tom Cherry17b77582020-06-17 11:40:55 -0700461 for (const auto& it : tidTable) {
Tom Cherryf1910142020-05-19 19:01:16 -0700462 const char* name = it.second.name();
Mark Salyzyn17e72122016-10-06 09:55:21 -0700463 if (name) size += strlen(name) + 1;
464 }
Tom Cherry17b77582020-06-17 11:40:55 -0700465 for (const auto& it : tagNameTable) {
Tom Cherry8a34ac42020-06-03 15:38:32 -0700466 size += sizeof(std::string);
467 size_t len = it.first.size();
468 // Account for short string optimization: if the string's length is <= 22 bytes for 64
469 // bit or <= 10 bytes for 32 bit, then there is no additional allocation.
470 if ((sizeof(std::string) == 24 && len > 22) ||
471 (sizeof(std::string) != 24 && len > 10)) {
472 size += len;
473 }
474 }
Mark Salyzyn17e72122016-10-06 09:55:21 -0700475 log_id_for_each(id) {
476 size += uidTable[id].sizeOf();
Mark Salyzynb6c5c872016-10-06 10:09:24 -0700477 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn17e72122016-10-06 09:55:21 -0700478 size += pidSystemTable[id].sizeOf();
Tom Cherry8a34ac42020-06-03 15:38:32 -0700479 size += pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn17e72122016-10-06 09:55:21 -0700480 }
481 return size;
482 }
483
Tom Cherry479b5032020-05-07 14:44:43 -0700484 public:
Tom Cherryf0dc09b2020-07-09 09:51:16 -0700485 LogStatistics(bool enable_statistics, bool track_total_size,
486 std::optional<log_time> start_time = {});
Mark Salyzynd774bce2014-02-06 14:48:50 -0800487
Tom Cherrya91e0702020-05-19 17:48:42 -0700488 void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700489
Elliott Hughes225e5c62022-09-16 23:01:59 +0000490 // Add is for adding an element to the log buffer.
491 // Add the total size of the element to statistics.
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700492 void Add(LogStatisticsElement entry) EXCLUDES(lock_);
Elliott Hughes225e5c62022-09-16 23:01:59 +0000493 // Subtract is for removing an element from the log buffer.
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700494 // Subtract the total size of the element from statistics.
495 void Subtract(LogStatisticsElement entry) EXCLUDES(lock_);
Mark Salyzynfe639a02014-02-19 17:18:31 -0800496
Tom Cherry479b5032020-05-07 14:44:43 -0700497 bool ShouldPrune(log_id id, unsigned long max_size, unsigned long* prune_rows) const
498 EXCLUDES(lock_);
499
Tom Cherry9a92d572020-08-05 11:22:44 -0700500 // Return the consumed size of the given buffer.
Tom Cherry479b5032020-05-07 14:44:43 -0700501 size_t Sizes(log_id_t id) const EXCLUDES(lock_) {
502 auto lock = std::lock_guard{lock_};
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700503 if (overhead_[id]) {
504 return *overhead_[id];
505 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800506 return mSizes[id];
507 }
Tom Cherry9a92d572020-08-05 11:22:44 -0700508
509 // Return the uncompressed size of the contents of the given buffer.
510 size_t SizeReadable(log_id_t id) const EXCLUDES(lock_) {
511 auto lock = std::lock_guard{lock_};
512 return mSizes[id];
513 }
514
Tom Cherry479b5032020-05-07 14:44:43 -0700515 // TODO: Get rid of this entirely.
Mark Salyzyn65059532017-03-10 14:31:54 -0800516 static size_t sizesTotal() {
517 return SizesTotal;
518 }
Mark Salyzynd774bce2014-02-06 14:48:50 -0800519
Tom Cherryf0dc09b2020-07-09 09:51:16 -0700520 std::string ReportInteresting() const EXCLUDES(lock_);
Tom Cherry479b5032020-05-07 14:44:43 -0700521 std::string Format(uid_t uid, pid_t pid, unsigned int logMask) const EXCLUDES(lock_);
Mark Salyzyn5766f802014-04-07 07:05:40 -0700522
Tom Cherry479b5032020-05-07 14:44:43 -0700523 const char* PidToName(pid_t pid) const EXCLUDES(lock_);
524 uid_t PidToUid(pid_t pid) EXCLUDES(lock_);
525 const char* UidToName(uid_t uid) const EXCLUDES(lock_);
Mark Salyzynd774bce2014-02-06 14:48:50 -0800526
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700527 void set_overhead(log_id_t id, size_t size) {
528 auto lock = std::lock_guard{lock_};
529 overhead_[id] = size;
530 }
531
Tom Cherry4011d5a2020-05-07 09:13:12 -0700532 private:
533 template <typename TKey, typename TEntry>
Tom Cherry479b5032020-05-07 14:44:43 -0700534 std::string FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid, pid_t pid,
535 const std::string& name = std::string(""),
536 log_id_t id = LOG_ID_MAX) const REQUIRES(lock_);
537 void FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size,
538 size_t nameLen) const REQUIRES(lock_);
539 const char* UidToNameLocked(uid_t uid) const REQUIRES(lock_);
540
541 mutable std::mutex lock_;
Tom Cherrya3d6aa62020-06-19 12:21:21 -0700542 bool track_total_size_;
543
544 std::optional<size_t> overhead_[LOG_ID_MAX] GUARDED_BY(lock_);
Tom Cherry4011d5a2020-05-07 09:13:12 -0700545};