blob: 7d13ff757dc37759cb8e9cde18c6bd48a7cbac92 [file] [log] [blame]
Mark Salyzyn34facab2014-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 Cherryb6b78e92020-05-07 09:13:12 -070017#pragma once
Mark Salyzyn34facab2014-02-06 14:48:50 -080018
Mark Salyzynb545e1c2016-12-19 14:51:15 -080019#include <ctype.h>
Mark Salyzynf99a7d62017-04-19 14:39:21 -070020#include <inttypes.h>
21#include <stdint.h>
Mark Salyzyn720f6d12015-03-16 08:26:05 -070022#include <stdlib.h>
Mark Salyzynf99a7d62017-04-19 14:39:21 -070023#include <string.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080024#include <sys/types.h>
25
Mark Salyzyn501c3732017-03-10 14:31:54 -080026#include <algorithm> // std::max
Tom Cherryb6b78e92020-05-07 09:13:12 -070027#include <array>
Mark Salyzynb545e1c2016-12-19 14:51:15 -080028#include <memory>
Tom Cherry64e90162020-05-07 14:44:43 -070029#include <mutex>
Elliott Hughese8058832017-11-30 16:31:35 -080030#include <string>
31#include <string_view>
Mark Salyzyn511338d2015-05-19 09:12:30 -070032#include <unordered_map>
33
Elliott Hughes4f713192015-12-04 22:00:26 -080034#include <android-base/stringprintf.h>
Tom Cherry64e90162020-05-07 14:44:43 -070035#include <android-base/thread_annotations.h>
Mark Salyzyn501c3732017-03-10 14:31:54 -080036#include <android/log.h>
Mark Salyzyn03bb7592017-04-14 09:46:57 -070037#include <log/log_time.h>
Mark Salyzyn758058f2015-08-21 16:44:30 -070038#include <private/android_filesystem_config.h>
Mark Salyzynf99a7d62017-04-19 14:39:21 -070039#include <utils/FastStrcmp.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070040
41#include "LogBufferElement.h"
Mark Salyzyn5ac5c6b2015-08-28 08:02:59 -070042#include "LogUtils.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080043
44#define log_id_for_each(i) \
Mark Salyzyn501c3732017-03-10 14:31:54 -080045 for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1))
Mark Salyzyn34facab2014-02-06 14:48:50 -080046
Mark Salyzyn758058f2015-08-21 16:44:30 -070047class LogStatistics;
48
Mark Salyzyn720f6d12015-03-16 08:26:05 -070049template <typename TKey, typename TEntry>
Mark Salyzyn511338d2015-05-19 09:12:30 -070050class LogHashtable {
Mark Salyzyn511338d2015-05-19 09:12:30 -070051 std::unordered_map<TKey, TEntry> map;
52
Mark Salyzyn6d981af2016-10-06 09:55:21 -070053 size_t bucket_size() const {
54 size_t count = 0;
55 for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
56 size_t bucket_size = map.bucket_size(idx);
57 if (bucket_size == 0) bucket_size = 1;
58 count += bucket_size;
59 }
60 float load_factor = map.max_load_factor();
61 if (load_factor < 1.0) return count;
62 return count * load_factor;
63 }
64
65 static const size_t unordered_map_per_entry_overhead = sizeof(void*);
66 static const size_t unordered_map_bucket_overhead = sizeof(void*);
67
Mark Salyzyn501c3732017-03-10 14:31:54 -080068 public:
69 size_t size() const {
70 return map.size();
71 }
Mark Salyzynb0672292016-10-06 10:09:24 -070072
Mark Salyzyn6d981af2016-10-06 09:55:21 -070073 // Estimate unordered_map memory usage.
74 size_t sizeOf() const {
75 return sizeof(*this) +
Mark Salyzynb0672292016-10-06 10:09:24 -070076 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn6d981af2016-10-06 09:55:21 -070077 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
78 }
79
Mark Salyzyn511338d2015-05-19 09:12:30 -070080 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn501c3732017-03-10 14:31:54 -080081 typedef
82 typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn511338d2015-05-19 09:12:30 -070083
Tom Cherryb6b78e92020-05-07 09:13:12 -070084 // Returns a sorted array of up to len highest entries sorted by size. If fewer than len
85 // entries are found, their positions are set to nullptr.
86 template <size_t len>
87 void MaxEntries(uid_t uid, pid_t pid, std::array<const TEntry*, len>* out) const {
88 auto& retval = *out;
89 retval.fill(nullptr);
Mark Salyzyn501c3732017-03-10 14:31:54 -080090 for (const_iterator it = map.begin(); it != map.end(); ++it) {
91 const TEntry& entry = it->second;
Mark Salyzynee3b8382015-12-17 09:58:43 -080092
93 if ((uid != AID_ROOT) && (uid != entry.getUid())) {
94 continue;
95 }
96 if (pid && entry.getPid() && (pid != entry.getPid())) {
97 continue;
98 }
99
Mark Salyzyn758058f2015-08-21 16:44:30 -0700100 size_t sizes = entry.getSizes();
101 ssize_t index = len - 1;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800102 while ((!retval[index] || (sizes > retval[index]->getSizes())) &&
103 (--index >= 0))
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700104 ;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700105 if (++index < (ssize_t)len) {
106 size_t num = len - index - 1;
107 if (num) {
108 memmove(&retval[index + 1], &retval[index],
109 num * sizeof(retval[0]));
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700110 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700111 retval[index] = &entry;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700112 }
113 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700114 }
115
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700116 inline iterator add(const TKey& key, const LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700117 iterator it = map.find(key);
118 if (it == map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700119 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn511338d2015-05-19 09:12:30 -0700120 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700121 it->second.add(element);
Mark Salyzyn511338d2015-05-19 09:12:30 -0700122 }
123 return it;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700124 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700125
Mark Salyzyn511338d2015-05-19 09:12:30 -0700126 inline iterator add(TKey key) {
127 iterator it = map.find(key);
128 if (it == map.end()) {
129 it = map.insert(std::make_pair(key, TEntry(key))).first;
130 } else {
131 it->second.add(key);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700132 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700133 return it;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700134 }
135
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700136 void subtract(TKey&& key, const LogBufferElement* element) {
137 iterator it = map.find(std::move(key));
138 if ((it != map.end()) && it->second.subtract(element)) {
139 map.erase(it);
140 }
141 }
142
143 void subtract(const TKey& key, const LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700144 iterator it = map.find(key);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700145 if ((it != map.end()) && it->second.subtract(element)) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700146 map.erase(it);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700147 }
148 }
149
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700150 inline void drop(TKey key, const LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700151 iterator it = map.find(key);
152 if (it != map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700153 it->second.drop(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700154 }
155 }
156
Mark Salyzyn501c3732017-03-10 14:31:54 -0800157 inline iterator begin() {
158 return map.begin();
159 }
160 inline const_iterator begin() const {
161 return map.begin();
162 }
163 inline iterator end() {
164 return map.end();
165 }
166 inline const_iterator end() const {
167 return map.end();
168 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700169};
170
Mark Salyzyn758058f2015-08-21 16:44:30 -0700171namespace EntryBaseConstants {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800172static constexpr size_t pruned_len = 14;
173static constexpr size_t total_len = 80;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700174}
175
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700176struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700177 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700178
Mark Salyzyn501c3732017-03-10 14:31:54 -0800179 EntryBase() : size(0) {
180 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700181 explicit EntryBase(const LogBufferElement* element)
182 : size(element->getMsgLen()) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800183 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700184
Mark Salyzyn501c3732017-03-10 14:31:54 -0800185 size_t getSizes() const {
186 return size;
187 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700188
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700189 inline void add(const LogBufferElement* element) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800190 size += element->getMsgLen();
191 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700192 inline bool subtract(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700193 size -= element->getMsgLen();
194 return !size;
195 }
196
Mark Salyzyn501c3732017-03-10 14:31:54 -0800197 static std::string formatLine(const std::string& name,
198 const std::string& size,
199 const std::string& pruned) {
200 ssize_t drop_len =
201 std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
202 ssize_t size_len =
203 std::max(size.length() + 1, EntryBaseConstants::total_len -
204 name.length() - drop_len - 1);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700205
Mark Salyzyn501c3732017-03-10 14:31:54 -0800206 std::string ret = android::base::StringPrintf(
207 "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
208 (int)drop_len, pruned.c_str());
Mark Salyzynb545e1c2016-12-19 14:51:15 -0800209 // remove any trailing spaces
210 size_t pos = ret.size();
211 size_t len = 0;
212 while (pos && isspace(ret[--pos])) ++len;
213 if (len) ret.erase(pos + 1, len);
214 return ret + "\n";
Mark Salyzyn758058f2015-08-21 16:44:30 -0700215 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700216};
217
218struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700219 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800220
Mark Salyzyn501c3732017-03-10 14:31:54 -0800221 EntryBaseDropped() : dropped(0) {
222 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700223 explicit EntryBaseDropped(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800224 : EntryBase(element), dropped(element->getDropped()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700225 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800226
Mark Salyzyn501c3732017-03-10 14:31:54 -0800227 size_t getDropped() const {
228 return dropped;
229 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700230
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700231 inline void add(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700232 dropped += element->getDropped();
233 EntryBase::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700234 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700235 inline bool subtract(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700236 dropped -= element->getDropped();
237 return EntryBase::subtract(element) && !dropped;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700238 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700239 inline void drop(const LogBufferElement* element) {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700240 dropped += 1;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700241 EntryBase::subtract(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700242 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800243};
244
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700245struct UidEntry : public EntryBaseDropped {
246 const uid_t uid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800247 pid_t pid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700248
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700249 explicit UidEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800250 : EntryBaseDropped(element),
251 uid(element->getUid()),
252 pid(element->getPid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700253 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700254
Mark Salyzyn501c3732017-03-10 14:31:54 -0800255 inline const uid_t& getKey() const {
256 return uid;
257 }
258 inline const uid_t& getUid() const {
259 return getKey();
260 }
261 inline const pid_t& getPid() const {
262 return pid;
263 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800264
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700265 inline void add(const LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800266 if (pid != element->getPid()) {
267 pid = -1;
268 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800269 EntryBaseDropped::add(element);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800270 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700271
Mark Salyzyn501c3732017-03-10 14:31:54 -0800272 std::string formatHeader(const std::string& name, log_id_t id) const;
273 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700274};
275
Tom Cherry40da03b2019-06-28 13:21:27 -0700276namespace android {
277uid_t pidToUid(pid_t pid);
278}
279
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700280struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700281 const pid_t pid;
282 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800283 char* name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700284
Mark Salyzyn501c3732017-03-10 14:31:54 -0800285 explicit PidEntry(pid_t pid)
286 : EntryBaseDropped(),
287 pid(pid),
288 uid(android::pidToUid(pid)),
289 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700290 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700291 explicit PidEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800292 : EntryBaseDropped(element),
293 pid(element->getPid()),
294 uid(element->getUid()),
295 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700296 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800297 PidEntry(const PidEntry& element)
298 : EntryBaseDropped(element),
299 pid(element.pid),
300 uid(element.uid),
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700301 name(element.name ? strdup(element.name) : nullptr) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700302 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800303 ~PidEntry() {
304 free(name);
305 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700306
Mark Salyzyn501c3732017-03-10 14:31:54 -0800307 const pid_t& getKey() const {
308 return pid;
309 }
310 const pid_t& getPid() const {
311 return getKey();
312 }
313 const uid_t& getUid() const {
314 return uid;
315 }
316 const char* getName() const {
317 return name;
318 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700319
Mark Salyzyn758058f2015-08-21 16:44:30 -0700320 inline void add(pid_t newPid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800321 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700322 free(name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700323 name = nullptr;
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700324 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700325 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700326 name = android::pidToName(newPid);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700327 }
328 }
329
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700330 inline void add(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700331 uid_t incomingUid = element->getUid();
332 if (getUid() != incomingUid) {
333 uid = incomingUid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700334 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700335 name = android::pidToName(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700336 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700337 add(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700338 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700339 EntryBaseDropped::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700340 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700341
Mark Salyzyn501c3732017-03-10 14:31:54 -0800342 std::string formatHeader(const std::string& name, log_id_t id) const;
343 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700344};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700345
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700346struct TidEntry : public EntryBaseDropped {
347 const pid_t tid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800348 pid_t pid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700349 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800350 char* name;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700351
Mark Salyzyn501c3732017-03-10 14:31:54 -0800352 TidEntry(pid_t tid, pid_t pid)
353 : EntryBaseDropped(),
354 tid(tid),
355 pid(pid),
356 uid(android::pidToUid(tid)),
357 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700358 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700359 explicit TidEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800360 : EntryBaseDropped(element),
361 tid(element->getTid()),
362 pid(element->getPid()),
363 uid(element->getUid()),
364 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700365 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800366 TidEntry(const TidEntry& element)
367 : EntryBaseDropped(element),
368 tid(element.tid),
369 pid(element.pid),
370 uid(element.uid),
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700371 name(element.name ? strdup(element.name) : nullptr) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700372 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800373 ~TidEntry() {
374 free(name);
375 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700376
Mark Salyzyn501c3732017-03-10 14:31:54 -0800377 const pid_t& getKey() const {
378 return tid;
379 }
380 const pid_t& getTid() const {
381 return getKey();
382 }
383 const pid_t& getPid() const {
384 return pid;
385 }
386 const uid_t& getUid() const {
387 return uid;
388 }
389 const char* getName() const {
390 return name;
391 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700392
Mark Salyzyn758058f2015-08-21 16:44:30 -0700393 inline void add(pid_t incomingTid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800394 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700395 free(name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700396 name = nullptr;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700397 }
398 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700399 name = android::tidToName(incomingTid);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700400 }
401 }
402
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700403 inline void add(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700404 uid_t incomingUid = element->getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800405 pid_t incomingPid = element->getPid();
406 if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700407 uid = incomingUid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800408 pid = incomingPid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700409 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700410 name = android::tidToName(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700411 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700412 add(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700413 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700414 EntryBaseDropped::add(element);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700415 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700416
Mark Salyzyn501c3732017-03-10 14:31:54 -0800417 std::string formatHeader(const std::string& name, log_id_t id) const;
418 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700419};
420
Mark Salyzyn6a066942016-07-14 15:34:30 -0700421struct TagEntry : public EntryBaseDropped {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700422 const uint32_t tag;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800423 pid_t pid;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700424 uid_t uid;
425
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700426 explicit TagEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800427 : EntryBaseDropped(element),
428 tag(element->getTag()),
429 pid(element->getPid()),
430 uid(element->getUid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700431 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700432
Mark Salyzyn501c3732017-03-10 14:31:54 -0800433 const uint32_t& getKey() const {
434 return tag;
435 }
436 const pid_t& getPid() const {
437 return pid;
438 }
439 const uid_t& getUid() const {
440 return uid;
441 }
442 const char* getName() const {
443 return android::tagToName(tag);
444 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700445
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700446 inline void add(const LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800447 if (uid != element->getUid()) {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700448 uid = -1;
449 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800450 if (pid != element->getPid()) {
451 pid = -1;
452 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800453 EntryBaseDropped::add(element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700454 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700455
Mark Salyzyn501c3732017-03-10 14:31:54 -0800456 std::string formatHeader(const std::string& name, log_id_t id) const;
457 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700458};
459
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700460struct TagNameKey {
461 std::string* alloc;
Elliott Hughese8058832017-11-30 16:31:35 -0800462 std::string_view name; // Saves space if const char*
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700463
464 explicit TagNameKey(const LogBufferElement* element)
465 : alloc(nullptr), name("", strlen("")) {
466 if (element->isBinary()) {
467 uint32_t tag = element->getTag();
468 if (tag) {
469 const char* cp = android::tagToName(tag);
470 if (cp) {
Elliott Hughese8058832017-11-30 16:31:35 -0800471 name = std::string_view(cp, strlen(cp));
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700472 return;
473 }
474 }
475 alloc = new std::string(
476 android::base::StringPrintf("[%" PRIu32 "]", tag));
477 if (!alloc) return;
Elliott Hughese8058832017-11-30 16:31:35 -0800478 name = std::string_view(alloc->c_str(), alloc->size());
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700479 return;
480 }
481 const char* msg = element->getMsg();
482 if (!msg) {
Elliott Hughese8058832017-11-30 16:31:35 -0800483 name = std::string_view("chatty", strlen("chatty"));
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700484 return;
485 }
486 ++msg;
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700487 uint16_t len = element->getMsgLen();
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700488 len = (len <= 1) ? 0 : strnlen(msg, len - 1);
489 if (!len) {
Elliott Hughese8058832017-11-30 16:31:35 -0800490 name = std::string_view("<NULL>", strlen("<NULL>"));
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700491 return;
492 }
493 alloc = new std::string(msg, len);
494 if (!alloc) return;
Elliott Hughese8058832017-11-30 16:31:35 -0800495 name = std::string_view(alloc->c_str(), alloc->size());
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700496 }
497
Chih-Hung Hsieh747eb142018-09-25 11:16:22 -0700498 explicit TagNameKey(TagNameKey&& rval) noexcept
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700499 : alloc(rval.alloc), name(rval.name.data(), rval.name.length()) {
500 rval.alloc = nullptr;
501 }
502
503 explicit TagNameKey(const TagNameKey& rval)
504 : alloc(rval.alloc ? new std::string(*rval.alloc) : nullptr),
505 name(alloc ? alloc->data() : rval.name.data(), rval.name.length()) {
506 }
507
508 ~TagNameKey() {
509 if (alloc) delete alloc;
510 }
511
Elliott Hughese8058832017-11-30 16:31:35 -0800512 operator const std::string_view() const {
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700513 return name;
514 }
515
516 const char* data() const {
517 return name.data();
518 }
519 size_t length() const {
520 return name.length();
521 }
522
523 bool operator==(const TagNameKey& rval) const {
524 if (length() != rval.length()) return false;
525 if (length() == 0) return true;
526 return fastcmp<strncmp>(data(), rval.data(), length()) == 0;
527 }
528 bool operator!=(const TagNameKey& rval) const {
529 return !(*this == rval);
530 }
531
532 size_t getAllocLength() const {
533 return alloc ? alloc->length() + 1 + sizeof(std::string) : 0;
534 }
535};
536
537// Hash for TagNameKey
538template <>
539struct std::hash<TagNameKey>
540 : public std::unary_function<const TagNameKey&, size_t> {
541 size_t operator()(const TagNameKey& __t) const noexcept {
542 if (!__t.length()) return 0;
Elliott Hughese8058832017-11-30 16:31:35 -0800543 return std::hash<std::string_view>()(std::string_view(__t));
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700544 }
545};
546
547struct TagNameEntry : public EntryBase {
548 pid_t tid;
549 pid_t pid;
550 uid_t uid;
551 TagNameKey name;
552
553 explicit TagNameEntry(const LogBufferElement* element)
554 : EntryBase(element),
555 tid(element->getTid()),
556 pid(element->getPid()),
557 uid(element->getUid()),
558 name(element) {
559 }
560
561 const TagNameKey& getKey() const {
562 return name;
563 }
564 const pid_t& getTid() const {
565 return tid;
566 }
567 const pid_t& getPid() const {
568 return pid;
569 }
570 const uid_t& getUid() const {
571 return uid;
572 }
573 const char* getName() const {
574 return name.data();
575 }
576 size_t getNameAllocLength() const {
577 return name.getAllocLength();
578 }
579
580 inline void add(const LogBufferElement* element) {
581 if (uid != element->getUid()) {
582 uid = -1;
583 }
584 if (pid != element->getPid()) {
585 pid = -1;
586 }
587 if (tid != element->getTid()) {
588 tid = -1;
589 }
590 EntryBase::add(element);
591 }
592
593 std::string formatHeader(const std::string& name, log_id_t id) const;
594 std::string format(const LogStatistics& stat, log_id_t id) const;
595};
596
Mark Salyzyn34facab2014-02-06 14:48:50 -0800597// Log Statistics
598class LogStatistics {
Mark Salyzync723df82015-08-24 11:08:00 -0700599 friend UidEntry;
Tom Cherry64e90162020-05-07 14:44:43 -0700600 friend PidEntry;
601 friend TidEntry;
Mark Salyzync723df82015-08-24 11:08:00 -0700602
Tom Cherry64e90162020-05-07 14:44:43 -0700603 size_t mSizes[LOG_ID_MAX] GUARDED_BY(lock_);
604 size_t mElements[LOG_ID_MAX] GUARDED_BY(lock_);
605 size_t mDroppedElements[LOG_ID_MAX] GUARDED_BY(lock_);
606 size_t mSizesTotal[LOG_ID_MAX] GUARDED_BY(lock_);
607 size_t mElementsTotal[LOG_ID_MAX] GUARDED_BY(lock_);
608 log_time mOldest[LOG_ID_MAX] GUARDED_BY(lock_);
609 log_time mNewest[LOG_ID_MAX] GUARDED_BY(lock_);
610 log_time mNewestDropped[LOG_ID_MAX] GUARDED_BY(lock_);
611 static std::atomic<size_t> SizesTotal;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700612 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800613
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700614 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700615 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Tom Cherry64e90162020-05-07 14:44:43 -0700616 uidTable_t uidTable[LOG_ID_MAX] GUARDED_BY(lock_);
Mark Salyzyne457b742014-02-19 17:18:31 -0800617
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700618 // pid of system to size list
619 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
Tom Cherry64e90162020-05-07 14:44:43 -0700620 pidSystemTable_t pidSystemTable[LOG_ID_MAX] GUARDED_BY(lock_);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700621
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700622 // pid to uid list
623 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
Tom Cherry64e90162020-05-07 14:44:43 -0700624 pidTable_t pidTable GUARDED_BY(lock_);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700625
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700626 // tid to uid list
627 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
Tom Cherry64e90162020-05-07 14:44:43 -0700628 tidTable_t tidTable GUARDED_BY(lock_);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700629
Mark Salyzyn344bff42015-04-13 14:24:45 -0700630 // tag list
631 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
Tom Cherry64e90162020-05-07 14:44:43 -0700632 tagTable_t tagTable GUARDED_BY(lock_);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700633
Mark Salyzyn083b0372015-12-04 10:59:45 -0800634 // security tag list
Tom Cherry64e90162020-05-07 14:44:43 -0700635 tagTable_t securityTagTable GUARDED_BY(lock_);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800636
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700637 // global tag list
638 typedef LogHashtable<TagNameKey, TagNameEntry> tagNameTable_t;
639 tagNameTable_t tagNameTable;
640
Tom Cherry64e90162020-05-07 14:44:43 -0700641 size_t sizeOf() const REQUIRES(lock_) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700642 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700643 tagTable.sizeOf() + securityTagTable.sizeOf() +
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700644 tagNameTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700645 (pidTable.size() * sizeof(pidTable_t::iterator)) +
646 (tagTable.size() * sizeof(tagTable_t::iterator));
Mark Salyzyn501c3732017-03-10 14:31:54 -0800647 for (auto it : pidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700648 const char* name = it.second.getName();
649 if (name) size += strlen(name) + 1;
650 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800651 for (auto it : tidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700652 const char* name = it.second.getName();
653 if (name) size += strlen(name) + 1;
654 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700655 for (auto it : tagNameTable) size += it.second.getNameAllocLength();
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700656 log_id_for_each(id) {
657 size += uidTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700658 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700659 size += pidSystemTable[id].sizeOf();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800660 size +=
661 pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700662 }
663 return size;
664 }
665
Tom Cherry64e90162020-05-07 14:44:43 -0700666 public:
667 LogStatistics(bool enable_statistics);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800668
Tom Cherrya26f7df2020-05-19 17:48:42 -0700669 void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
Tom Cherry64e90162020-05-07 14:44:43 -0700670 void Add(LogBufferElement* entry) EXCLUDES(lock_);
671 void Subtract(LogBufferElement* entry) EXCLUDES(lock_);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700672 // entry->setDropped(1) must follow this call
Tom Cherry64e90162020-05-07 14:44:43 -0700673 void Drop(LogBufferElement* entry) EXCLUDES(lock_);
Mark Salyzynaaad42f2015-09-30 07:40:09 -0700674 // Correct for coalescing two entries referencing dropped content
Tom Cherry64e90162020-05-07 14:44:43 -0700675 void Erase(LogBufferElement* element) EXCLUDES(lock_) {
676 auto lock = std::lock_guard{lock_};
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700677 log_id_t log_id = element->getLogId();
678 --mElements[log_id];
679 --mDroppedElements[log_id];
680 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800681
Tom Cherryb6b78e92020-05-07 09:13:12 -0700682 void WorstTwoUids(log_id id, size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700683 size_t* second_worst_sizes) const EXCLUDES(lock_);
Tom Cherryb6b78e92020-05-07 09:13:12 -0700684 void WorstTwoTags(size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700685 size_t* second_worst_sizes) const EXCLUDES(lock_);
Tom Cherryb6b78e92020-05-07 09:13:12 -0700686 void WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* worst,
Tom Cherry64e90162020-05-07 14:44:43 -0700687 size_t* second_worst_sizes) const EXCLUDES(lock_);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800688
Tom Cherry64e90162020-05-07 14:44:43 -0700689 bool ShouldPrune(log_id id, unsigned long max_size, unsigned long* prune_rows) const
690 EXCLUDES(lock_);
691
692 // Snapshot of the sizes for a given log buffer.
693 size_t Sizes(log_id_t id) const EXCLUDES(lock_) {
694 auto lock = std::lock_guard{lock_};
Mark Salyzyn501c3732017-03-10 14:31:54 -0800695 return mSizes[id];
696 }
Tom Cherry64e90162020-05-07 14:44:43 -0700697 // TODO: Get rid of this entirely.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800698 static size_t sizesTotal() {
699 return SizesTotal;
700 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800701
Tom Cherry64e90162020-05-07 14:44:43 -0700702 std::string Format(uid_t uid, pid_t pid, unsigned int logMask) const EXCLUDES(lock_);
Mark Salyzyn9a038632014-04-07 07:05:40 -0700703
Tom Cherry64e90162020-05-07 14:44:43 -0700704 const char* PidToName(pid_t pid) const EXCLUDES(lock_);
705 uid_t PidToUid(pid_t pid) EXCLUDES(lock_);
706 const char* UidToName(uid_t uid) const EXCLUDES(lock_);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800707
Tom Cherryb6b78e92020-05-07 09:13:12 -0700708 private:
709 template <typename TKey, typename TEntry>
710 void WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& table, size_t threshold,
Tom Cherry64e90162020-05-07 14:44:43 -0700711 int* worst, size_t* worst_sizes, size_t* second_worst_sizes) const;
712 template <typename TKey, typename TEntry>
713 std::string FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid, pid_t pid,
714 const std::string& name = std::string(""),
715 log_id_t id = LOG_ID_MAX) const REQUIRES(lock_);
716 void FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size,
717 size_t nameLen) const REQUIRES(lock_);
718 const char* UidToNameLocked(uid_t uid) const REQUIRES(lock_);
719
720 mutable std::mutex lock_;
Tom Cherryb6b78e92020-05-07 09:13:12 -0700721};