blob: cb7ae2b69680a98d13b9bed7bea1f4c9441ba362 [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
17#ifndef _LOGD_LOG_STATISTICS_H__
18#define _LOGD_LOG_STATISTICS_H__
19
Mark Salyzyn720f6d12015-03-16 08:26:05 -070020#include <memory>
21#include <stdlib.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080022#include <sys/types.h>
23
Mark Salyzyn758058f2015-08-21 16:44:30 -070024#include <algorithm> // std::max
25#include <string> // std::string
Mark Salyzyn511338d2015-05-19 09:12:30 -070026#include <unordered_map>
27
Mark Salyzyn0dd44312016-09-28 15:54:45 -070028#include <android/log.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080029#include <android-base/stringprintf.h>
Mark Salyzyn758058f2015-08-21 16:44:30 -070030#include <private/android_filesystem_config.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070031
32#include "LogBufferElement.h"
Mark Salyzyn5ac5c6b2015-08-28 08:02:59 -070033#include "LogUtils.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080034
35#define log_id_for_each(i) \
Chih-Hung Hsiehf0f94fe2016-05-18 15:47:19 -070036 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 -080037
Mark Salyzyn758058f2015-08-21 16:44:30 -070038class LogStatistics;
39
Mark Salyzyn720f6d12015-03-16 08:26:05 -070040template <typename TKey, typename TEntry>
Mark Salyzyn511338d2015-05-19 09:12:30 -070041class LogHashtable {
42
43 std::unordered_map<TKey, TEntry> map;
44
Mark Salyzyn6d981af2016-10-06 09:55:21 -070045 size_t bucket_size() const {
46 size_t count = 0;
47 for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
48 size_t bucket_size = map.bucket_size(idx);
49 if (bucket_size == 0) bucket_size = 1;
50 count += bucket_size;
51 }
52 float load_factor = map.max_load_factor();
53 if (load_factor < 1.0) return count;
54 return count * load_factor;
55 }
56
57 static const size_t unordered_map_per_entry_overhead = sizeof(void*);
58 static const size_t unordered_map_bucket_overhead = sizeof(void*);
59
Mark Salyzyn720f6d12015-03-16 08:26:05 -070060public:
Mark Salyzyn511338d2015-05-19 09:12:30 -070061
Mark Salyzynb0672292016-10-06 10:09:24 -070062 size_t size() const { return map.size(); }
63
Mark Salyzyn6d981af2016-10-06 09:55:21 -070064 // Estimate unordered_map memory usage.
65 size_t sizeOf() const {
66 return sizeof(*this) +
Mark Salyzynb0672292016-10-06 10:09:24 -070067 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn6d981af2016-10-06 09:55:21 -070068 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
69 }
70
Mark Salyzyn511338d2015-05-19 09:12:30 -070071 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn758058f2015-08-21 16:44:30 -070072 typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn511338d2015-05-19 09:12:30 -070073
Mark Salyzynee3b8382015-12-17 09:58:43 -080074 std::unique_ptr<const TEntry *[]> sort(uid_t uid, pid_t pid,
75 size_t len) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -070076 if (!len) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -070077 std::unique_ptr<const TEntry *[]> sorted(NULL);
78 return sorted;
79 }
80
Mark Salyzyn758058f2015-08-21 16:44:30 -070081 const TEntry **retval = new const TEntry* [len];
82 memset(retval, 0, sizeof(*retval) * len);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070083
Mark Salyzyn758058f2015-08-21 16:44:30 -070084 for(const_iterator it = map.begin(); it != map.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -070085 const TEntry &entry = it->second;
Mark Salyzynee3b8382015-12-17 09:58:43 -080086
87 if ((uid != AID_ROOT) && (uid != entry.getUid())) {
88 continue;
89 }
90 if (pid && entry.getPid() && (pid != entry.getPid())) {
91 continue;
92 }
93
Mark Salyzyn758058f2015-08-21 16:44:30 -070094 size_t sizes = entry.getSizes();
95 ssize_t index = len - 1;
96 while ((!retval[index] || (sizes > retval[index]->getSizes()))
97 && (--index >= 0))
Mark Salyzyn720f6d12015-03-16 08:26:05 -070098 ;
Mark Salyzyn758058f2015-08-21 16:44:30 -070099 if (++index < (ssize_t)len) {
100 size_t num = len - index - 1;
101 if (num) {
102 memmove(&retval[index + 1], &retval[index],
103 num * sizeof(retval[0]));
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700104 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700105 retval[index] = &entry;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700106 }
107 }
108 std::unique_ptr<const TEntry *[]> sorted(retval);
109 return sorted;
110 }
111
Mark Salyzyn758058f2015-08-21 16:44:30 -0700112 inline iterator add(TKey key, LogBufferElement *element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700113 iterator it = map.find(key);
114 if (it == map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700115 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn511338d2015-05-19 09:12:30 -0700116 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700117 it->second.add(element);
Mark Salyzyn511338d2015-05-19 09:12:30 -0700118 }
119 return it;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700120 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700121
Mark Salyzyn511338d2015-05-19 09:12:30 -0700122 inline iterator add(TKey key) {
123 iterator it = map.find(key);
124 if (it == map.end()) {
125 it = map.insert(std::make_pair(key, TEntry(key))).first;
126 } else {
127 it->second.add(key);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700128 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700129 return it;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700130 }
131
Mark Salyzyn758058f2015-08-21 16:44:30 -0700132 void subtract(TKey key, LogBufferElement *element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700133 iterator it = map.find(key);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700134 if ((it != map.end()) && it->second.subtract(element)) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700135 map.erase(it);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700136 }
137 }
138
Mark Salyzyn758058f2015-08-21 16:44:30 -0700139 inline void drop(TKey key, LogBufferElement *element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700140 iterator it = map.find(key);
141 if (it != map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700142 it->second.drop(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700143 }
144 }
145
Mark Salyzyn511338d2015-05-19 09:12:30 -0700146 inline iterator begin() { return map.begin(); }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700147 inline const_iterator begin() const { return map.begin(); }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700148 inline iterator end() { return map.end(); }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700149 inline const_iterator end() const { return map.end(); }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700150
Mark Salyzyn758058f2015-08-21 16:44:30 -0700151 std::string format(
152 const LogStatistics &stat,
153 uid_t uid,
Mark Salyzynee3b8382015-12-17 09:58:43 -0800154 pid_t pid,
Mark Salyzyn758058f2015-08-21 16:44:30 -0700155 const std::string &name = std::string(""),
156 log_id_t id = LOG_ID_MAX) const {
157 static const size_t maximum_sorted_entries = 32;
158 std::string output;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800159 std::unique_ptr<const TEntry *[]> sorted = sort(uid, pid,
160 maximum_sorted_entries);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700161 if (!sorted.get()) {
162 return output;
163 }
164 bool headerPrinted = false;
165 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
166 const TEntry *entry = sorted[index];
167 if (!entry) {
168 break;
169 }
170 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
171 break;
172 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700173 if (!headerPrinted) {
174 output += "\n\n";
175 output += entry->formatHeader(name, id);
176 headerPrinted = true;
177 }
178 output += entry->format(stat, id);
179 }
180 return output;
181 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700182
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700183};
184
Mark Salyzyn758058f2015-08-21 16:44:30 -0700185namespace EntryBaseConstants {
186 static constexpr size_t pruned_len = 14;
187 static constexpr size_t total_len = 80;
188}
189
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700190struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700191 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700192
193 EntryBase():size(0) { }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700194 explicit EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700195
196 size_t getSizes() const { return size; }
197
Mark Salyzyn758058f2015-08-21 16:44:30 -0700198 inline void add(LogBufferElement *element) { size += element->getMsgLen(); }
199 inline bool subtract(LogBufferElement *element) {
200 size -= element->getMsgLen();
201 return !size;
202 }
203
204 static std::string formatLine(
205 const std::string &name,
206 const std::string &size,
207 const std::string &pruned) {
208 ssize_t drop_len = std::max(pruned.length() + 1,
209 EntryBaseConstants::pruned_len);
210 ssize_t size_len = std::max(size.length() + 1,
211 EntryBaseConstants::total_len
212 - name.length() - drop_len - 1);
213
214 if (pruned.length()) {
215 return android::base::StringPrintf("%s%*s%*s\n", name.c_str(),
216 (int)size_len, size.c_str(),
217 (int)drop_len, pruned.c_str());
218 } else {
219 return android::base::StringPrintf("%s%*s\n", name.c_str(),
220 (int)size_len, size.c_str());
221 }
222 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700223};
224
225struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700226 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800227
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700228 EntryBaseDropped():dropped(0) { }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700229 explicit EntryBaseDropped(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700230 EntryBase(element),
Mark Salyzyn6a066942016-07-14 15:34:30 -0700231 dropped(element->getDropped()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700232 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800233
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700234 size_t getDropped() const { return dropped; }
235
Mark Salyzyn758058f2015-08-21 16:44:30 -0700236 inline void add(LogBufferElement *element) {
237 dropped += element->getDropped();
238 EntryBase::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700239 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700240 inline bool subtract(LogBufferElement *element) {
241 dropped -= element->getDropped();
242 return EntryBase::subtract(element) && !dropped;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700243 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700244 inline void drop(LogBufferElement *element) {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700245 dropped += 1;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700246 EntryBase::subtract(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700247 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800248};
249
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700250struct UidEntry : public EntryBaseDropped {
251 const uid_t uid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800252 pid_t pid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700253
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700254 explicit UidEntry(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700255 EntryBaseDropped(element),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800256 uid(element->getUid()),
257 pid(element->getPid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700258 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700259
260 inline const uid_t&getKey() const { return uid; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800261 inline const uid_t&getUid() const { return getKey(); }
262 inline const pid_t&getPid() const { return pid; }
263
264 inline void add(LogBufferElement *element) {
265 if (pid != element->getPid()) {
266 pid = -1;
267 }
268 EntryBase::add(element);
269 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700270
271 std::string formatHeader(const std::string &name, log_id_t id) const;
272 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700273};
274
275namespace android {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700276uid_t pidToUid(pid_t pid);
277}
278
279struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700280 const pid_t pid;
281 uid_t uid;
282 char *name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700283
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700284 explicit PidEntry(pid_t pid):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700285 EntryBaseDropped(),
286 pid(pid),
287 uid(android::pidToUid(pid)),
288 name(android::pidToName(pid)) {
289 }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700290 explicit PidEntry(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700291 EntryBaseDropped(element),
292 pid(element->getPid()),
293 uid(element->getUid()),
294 name(android::pidToName(pid)) {
295 }
296 PidEntry(const PidEntry &element):
297 EntryBaseDropped(element),
298 pid(element.pid),
299 uid(element.uid),
300 name(element.name ? strdup(element.name) : NULL) {
301 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700302 ~PidEntry() { free(name); }
303
304 const pid_t&getKey() const { return pid; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800305 const pid_t&getPid() const { return getKey(); }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700306 const uid_t&getUid() const { return uid; }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700307 const char*getName() const { return name; }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700308
Mark Salyzyn758058f2015-08-21 16:44:30 -0700309 inline void add(pid_t newPid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800310 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700311 free(name);
312 name = NULL;
313 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700314 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700315 name = android::pidToName(newPid);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700316 }
317 }
318
Mark Salyzyn758058f2015-08-21 16:44:30 -0700319 inline void add(LogBufferElement *element) {
320 uid_t incomingUid = element->getUid();
321 if (getUid() != incomingUid) {
322 uid = incomingUid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700323 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700324 name = android::pidToName(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700325 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700326 add(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700327 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700328 EntryBaseDropped::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700329 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700330
331 std::string formatHeader(const std::string &name, log_id_t id) const;
332 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700333};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700334
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700335struct TidEntry : public EntryBaseDropped {
336 const pid_t tid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800337 pid_t pid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700338 uid_t uid;
339 char *name;
340
Mark Salyzynee3b8382015-12-17 09:58:43 -0800341 TidEntry(pid_t tid, pid_t pid):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700342 EntryBaseDropped(),
343 tid(tid),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800344 pid(pid),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700345 uid(android::pidToUid(tid)),
346 name(android::tidToName(tid)) {
347 }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700348 explicit TidEntry(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700349 EntryBaseDropped(element),
350 tid(element->getTid()),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800351 pid(element->getPid()),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700352 uid(element->getUid()),
353 name(android::tidToName(tid)) {
354 }
355 TidEntry(const TidEntry &element):
356 EntryBaseDropped(element),
357 tid(element.tid),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800358 pid(element.pid),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700359 uid(element.uid),
360 name(element.name ? strdup(element.name) : NULL) {
361 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700362 ~TidEntry() { free(name); }
363
364 const pid_t&getKey() const { return tid; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800365 const pid_t&getTid() const { return getKey(); }
366 const pid_t&getPid() const { return pid; }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700367 const uid_t&getUid() const { return uid; }
368 const char*getName() const { return name; }
369
Mark Salyzyn758058f2015-08-21 16:44:30 -0700370 inline void add(pid_t incomingTid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800371 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700372 free(name);
373 name = NULL;
374 }
375 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700376 name = android::tidToName(incomingTid);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700377 }
378 }
379
Mark Salyzyn758058f2015-08-21 16:44:30 -0700380 inline void add(LogBufferElement *element) {
381 uid_t incomingUid = element->getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800382 pid_t incomingPid = element->getPid();
383 if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700384 uid = incomingUid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800385 pid = incomingPid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700386 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700387 name = android::tidToName(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700388 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700389 add(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700390 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700391 EntryBaseDropped::add(element);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700392 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700393
394 std::string formatHeader(const std::string &name, log_id_t id) const;
395 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700396};
397
Mark Salyzyn6a066942016-07-14 15:34:30 -0700398struct TagEntry : public EntryBaseDropped {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700399 const uint32_t tag;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800400 pid_t pid;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700401 uid_t uid;
402
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700403 explicit TagEntry(LogBufferElement *element):
Mark Salyzyn6a066942016-07-14 15:34:30 -0700404 EntryBaseDropped(element),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700405 tag(element->getTag()),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800406 pid(element->getPid()),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700407 uid(element->getUid()) {
408 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700409
410 const uint32_t&getKey() const { return tag; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800411 const pid_t&getPid() const { return pid; }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700412 const uid_t&getUid() const { return uid; }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700413 const char*getName(size_t &len) const { return android::tagToName(&len, tag); }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700414
Mark Salyzyn758058f2015-08-21 16:44:30 -0700415 inline void add(LogBufferElement *element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800416 if (uid != element->getUid()) {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700417 uid = -1;
418 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800419 if (pid != element->getPid()) {
420 pid = -1;
421 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700422 EntryBase::add(element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700423 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700424
425 std::string formatHeader(const std::string &name, log_id_t id) const;
426 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700427};
428
Mark Salyzyn6a066942016-07-14 15:34:30 -0700429template <typename TEntry>
430class LogFindWorst {
431 std::unique_ptr<const TEntry *[]> sorted;
432
433public:
434
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700435 explicit LogFindWorst(std::unique_ptr<const TEntry *[]> &&sorted) : sorted(std::move(sorted)) { }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700436
437 void findWorst(int &worst,
438 size_t &worst_sizes, size_t &second_worst_sizes,
439 size_t threshold) {
440 if (sorted.get() && sorted[0] && sorted[1]) {
441 worst_sizes = sorted[0]->getSizes();
442 if ((worst_sizes > threshold)
443 // Allow time horizon to extend roughly tenfold, assume
444 // average entry length is 100 characters.
445 && (worst_sizes > (10 * sorted[0]->getDropped()))) {
446 worst = sorted[0]->getKey();
447 second_worst_sizes = sorted[1]->getSizes();
448 if (second_worst_sizes < threshold) {
449 second_worst_sizes = threshold;
450 }
451 }
452 }
453 }
454
455 void findWorst(int &worst,
456 size_t worst_sizes, size_t &second_worst_sizes) {
457 if (sorted.get() && sorted[0] && sorted[1]) {
458 worst = sorted[0]->getKey();
459 second_worst_sizes = worst_sizes
460 - sorted[0]->getSizes()
461 + sorted[1]->getSizes();
462 }
463 }
464};
465
Mark Salyzyn34facab2014-02-06 14:48:50 -0800466// Log Statistics
467class LogStatistics {
Mark Salyzync723df82015-08-24 11:08:00 -0700468 friend UidEntry;
469
Mark Salyzyn34facab2014-02-06 14:48:50 -0800470 size_t mSizes[LOG_ID_MAX];
471 size_t mElements[LOG_ID_MAX];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700472 size_t mDroppedElements[LOG_ID_MAX];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700473 size_t mSizesTotal[LOG_ID_MAX];
474 size_t mElementsTotal[LOG_ID_MAX];
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700475 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800476
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700477 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700478 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700479 uidTable_t uidTable[LOG_ID_MAX];
Mark Salyzyne457b742014-02-19 17:18:31 -0800480
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700481 // pid of system to size list
482 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
483 pidSystemTable_t pidSystemTable[LOG_ID_MAX];
484
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700485 // pid to uid list
486 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
487 pidTable_t pidTable;
488
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700489 // tid to uid list
490 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
491 tidTable_t tidTable;
492
Mark Salyzyn344bff42015-04-13 14:24:45 -0700493 // tag list
494 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
495 tagTable_t tagTable;
496
Mark Salyzyn083b0372015-12-04 10:59:45 -0800497 // security tag list
498 tagTable_t securityTagTable;
499
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700500 size_t sizeOf() const {
501 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700502 tagTable.sizeOf() + securityTagTable.sizeOf() +
503 (pidTable.size() * sizeof(pidTable_t::iterator)) +
504 (tagTable.size() * sizeof(tagTable_t::iterator));
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700505 for(auto it : pidTable) {
506 const char* name = it.second.getName();
507 if (name) size += strlen(name) + 1;
508 }
509 for(auto it : tidTable) {
510 const char* name = it.second.getName();
511 if (name) size += strlen(name) + 1;
512 }
513 log_id_for_each(id) {
514 size += uidTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700515 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700516 size += pidSystemTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700517 size += pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700518 }
519 return size;
520 }
521
Mark Salyzyn34facab2014-02-06 14:48:50 -0800522public:
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700523
Mark Salyzyn34facab2014-02-06 14:48:50 -0800524 LogStatistics();
525
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700526 void enableStatistics() { enable = true; }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800527
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700528 void add(LogBufferElement *entry);
529 void subtract(LogBufferElement *entry);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700530 // entry->setDropped(1) must follow this call
531 void drop(LogBufferElement *entry);
Mark Salyzynaaad42f2015-09-30 07:40:09 -0700532 // Correct for coalescing two entries referencing dropped content
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700533 void erase(LogBufferElement *element) {
534 log_id_t log_id = element->getLogId();
535 --mElements[log_id];
536 --mDroppedElements[log_id];
537 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800538
Mark Salyzyn6a066942016-07-14 15:34:30 -0700539 LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
540 return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700541 }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700542 LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len, log_id id) {
543 return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
544 }
545 LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
546 return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700547 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800548
549 // fast track current value by id only
550 size_t sizes(log_id_t id) const { return mSizes[id]; }
551 size_t elements(log_id_t id) const { return mElements[id]; }
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700552 size_t realElements(log_id_t id) const {
553 return mElements[id] - mDroppedElements[id];
554 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700555 size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
556 size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800557
Mark Salyzynee3b8382015-12-17 09:58:43 -0800558 std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
Mark Salyzyn9a038632014-04-07 07:05:40 -0700559
Mark Salyzyned777e92015-06-24 16:22:54 -0700560 // helper (must be locked directly or implicitly by mLogElementsLock)
Mark Salyzyn758058f2015-08-21 16:44:30 -0700561 const char *pidToName(pid_t pid) const;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700562 uid_t pidToUid(pid_t pid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700563 const char *uidToName(uid_t uid) const;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800564};
565
566#endif // _LOGD_LOG_STATISTICS_H__