blob: 066b7de421df7fdae6c6183f1800beca25855719 [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 Salyzynb545e1c2016-12-19 14:51:15 -080020#include <ctype.h>
Mark Salyzyn720f6d12015-03-16 08:26:05 -070021#include <stdlib.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080022#include <sys/types.h>
23
Mark Salyzyn501c3732017-03-10 14:31:54 -080024#include <algorithm> // std::max
Mark Salyzynb545e1c2016-12-19 14:51:15 -080025#include <memory>
Mark Salyzyn501c3732017-03-10 14:31:54 -080026#include <string> // std::string
Mark Salyzyn511338d2015-05-19 09:12:30 -070027#include <unordered_map>
28
Elliott Hughes4f713192015-12-04 22:00:26 -080029#include <android-base/stringprintf.h>
Mark Salyzyn501c3732017-03-10 14:31:54 -080030#include <android/log.h>
Mark Salyzyn758058f2015-08-21 16:44:30 -070031#include <private/android_filesystem_config.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070032
33#include "LogBufferElement.h"
Mark Salyzyn5ac5c6b2015-08-28 08:02:59 -070034#include "LogUtils.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080035
36#define log_id_for_each(i) \
Mark Salyzyn501c3732017-03-10 14:31:54 -080037 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 -080038
Mark Salyzyn758058f2015-08-21 16:44:30 -070039class LogStatistics;
40
Mark Salyzyn720f6d12015-03-16 08:26:05 -070041template <typename TKey, typename TEntry>
Mark Salyzyn511338d2015-05-19 09:12:30 -070042class LogHashtable {
Mark Salyzyn511338d2015-05-19 09:12:30 -070043 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 Salyzyn501c3732017-03-10 14:31:54 -080060 public:
61 size_t size() const {
62 return map.size();
63 }
Mark Salyzynb0672292016-10-06 10:09:24 -070064
Mark Salyzyn6d981af2016-10-06 09:55:21 -070065 // Estimate unordered_map memory usage.
66 size_t sizeOf() const {
67 return sizeof(*this) +
Mark Salyzynb0672292016-10-06 10:09:24 -070068 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn6d981af2016-10-06 09:55:21 -070069 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
70 }
71
Mark Salyzyn511338d2015-05-19 09:12:30 -070072 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn501c3732017-03-10 14:31:54 -080073 typedef
74 typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn511338d2015-05-19 09:12:30 -070075
Mark Salyzyn501c3732017-03-10 14:31:54 -080076 std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid,
Mark Salyzynee3b8382015-12-17 09:58:43 -080077 size_t len) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -070078 if (!len) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080079 std::unique_ptr<const TEntry* []> sorted(NULL);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070080 return sorted;
81 }
82
Mark Salyzyn501c3732017-03-10 14:31:54 -080083 const TEntry** retval = new const TEntry*[len];
Mark Salyzyn758058f2015-08-21 16:44:30 -070084 memset(retval, 0, sizeof(*retval) * len);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070085
Mark Salyzyn501c3732017-03-10 14:31:54 -080086 for (const_iterator it = map.begin(); it != map.end(); ++it) {
87 const TEntry& entry = it->second;
Mark Salyzynee3b8382015-12-17 09:58:43 -080088
89 if ((uid != AID_ROOT) && (uid != entry.getUid())) {
90 continue;
91 }
92 if (pid && entry.getPid() && (pid != entry.getPid())) {
93 continue;
94 }
95
Mark Salyzyn758058f2015-08-21 16:44:30 -070096 size_t sizes = entry.getSizes();
97 ssize_t index = len - 1;
Mark Salyzyn501c3732017-03-10 14:31:54 -080098 while ((!retval[index] || (sizes > retval[index]->getSizes())) &&
99 (--index >= 0))
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700100 ;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700101 if (++index < (ssize_t)len) {
102 size_t num = len - index - 1;
103 if (num) {
104 memmove(&retval[index + 1], &retval[index],
105 num * sizeof(retval[0]));
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700106 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700107 retval[index] = &entry;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700108 }
109 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800110 std::unique_ptr<const TEntry* []> sorted(retval);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700111 return sorted;
112 }
113
Mark Salyzyn501c3732017-03-10 14:31:54 -0800114 inline iterator add(TKey key, LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700115 iterator it = map.find(key);
116 if (it == map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700117 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn511338d2015-05-19 09:12:30 -0700118 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700119 it->second.add(element);
Mark Salyzyn511338d2015-05-19 09:12:30 -0700120 }
121 return it;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700122 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700123
Mark Salyzyn511338d2015-05-19 09:12:30 -0700124 inline iterator add(TKey key) {
125 iterator it = map.find(key);
126 if (it == map.end()) {
127 it = map.insert(std::make_pair(key, TEntry(key))).first;
128 } else {
129 it->second.add(key);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700130 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700131 return it;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700132 }
133
Mark Salyzyn501c3732017-03-10 14:31:54 -0800134 void subtract(TKey key, LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700135 iterator it = map.find(key);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700136 if ((it != map.end()) && it->second.subtract(element)) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700137 map.erase(it);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700138 }
139 }
140
Mark Salyzyn501c3732017-03-10 14:31:54 -0800141 inline void drop(TKey key, LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700142 iterator it = map.find(key);
143 if (it != map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700144 it->second.drop(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700145 }
146 }
147
Mark Salyzyn501c3732017-03-10 14:31:54 -0800148 inline iterator begin() {
149 return map.begin();
150 }
151 inline const_iterator begin() const {
152 return map.begin();
153 }
154 inline iterator end() {
155 return map.end();
156 }
157 inline const_iterator end() const {
158 return map.end();
159 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700160
Mark Salyzyn501c3732017-03-10 14:31:54 -0800161 std::string format(const LogStatistics& stat, uid_t uid, pid_t pid,
162 const std::string& name = std::string(""),
163 log_id_t id = LOG_ID_MAX) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700164 static const size_t maximum_sorted_entries = 32;
165 std::string output;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800166 std::unique_ptr<const TEntry* []> sorted =
167 sort(uid, pid, maximum_sorted_entries);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700168 if (!sorted.get()) {
169 return output;
170 }
171 bool headerPrinted = false;
172 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800173 const TEntry* entry = sorted[index];
Mark Salyzyn758058f2015-08-21 16:44:30 -0700174 if (!entry) {
175 break;
176 }
177 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
178 break;
179 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700180 if (!headerPrinted) {
181 output += "\n\n";
182 output += entry->formatHeader(name, id);
183 headerPrinted = true;
184 }
185 output += entry->format(stat, id);
186 }
187 return output;
188 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700189};
190
Mark Salyzyn758058f2015-08-21 16:44:30 -0700191namespace EntryBaseConstants {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800192static constexpr size_t pruned_len = 14;
193static constexpr size_t total_len = 80;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700194}
195
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700196struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700197 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700198
Mark Salyzyn501c3732017-03-10 14:31:54 -0800199 EntryBase() : size(0) {
200 }
201 explicit EntryBase(LogBufferElement* element) : size(element->getMsgLen()) {
202 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700203
Mark Salyzyn501c3732017-03-10 14:31:54 -0800204 size_t getSizes() const {
205 return size;
206 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700207
Mark Salyzyn501c3732017-03-10 14:31:54 -0800208 inline void add(LogBufferElement* element) {
209 size += element->getMsgLen();
210 }
211 inline bool subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700212 size -= element->getMsgLen();
213 return !size;
214 }
215
Mark Salyzyn501c3732017-03-10 14:31:54 -0800216 static std::string formatLine(const std::string& name,
217 const std::string& size,
218 const std::string& pruned) {
219 ssize_t drop_len =
220 std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
221 ssize_t size_len =
222 std::max(size.length() + 1, EntryBaseConstants::total_len -
223 name.length() - drop_len - 1);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700224
Mark Salyzyn501c3732017-03-10 14:31:54 -0800225 std::string ret = android::base::StringPrintf(
226 "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
227 (int)drop_len, pruned.c_str());
Mark Salyzynb545e1c2016-12-19 14:51:15 -0800228 // remove any trailing spaces
229 size_t pos = ret.size();
230 size_t len = 0;
231 while (pos && isspace(ret[--pos])) ++len;
232 if (len) ret.erase(pos + 1, len);
233 return ret + "\n";
Mark Salyzyn758058f2015-08-21 16:44:30 -0700234 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700235};
236
237struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700238 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800239
Mark Salyzyn501c3732017-03-10 14:31:54 -0800240 EntryBaseDropped() : dropped(0) {
241 }
242 explicit EntryBaseDropped(LogBufferElement* element)
243 : EntryBase(element), dropped(element->getDropped()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700244 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800245
Mark Salyzyn501c3732017-03-10 14:31:54 -0800246 size_t getDropped() const {
247 return dropped;
248 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700249
Mark Salyzyn501c3732017-03-10 14:31:54 -0800250 inline void add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700251 dropped += element->getDropped();
252 EntryBase::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700253 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800254 inline bool subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700255 dropped -= element->getDropped();
256 return EntryBase::subtract(element) && !dropped;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700257 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800258 inline void drop(LogBufferElement* element) {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700259 dropped += 1;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700260 EntryBase::subtract(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700261 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800262};
263
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700264struct UidEntry : public EntryBaseDropped {
265 const uid_t uid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800266 pid_t pid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700267
Mark Salyzyn501c3732017-03-10 14:31:54 -0800268 explicit UidEntry(LogBufferElement* element)
269 : EntryBaseDropped(element),
270 uid(element->getUid()),
271 pid(element->getPid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700272 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700273
Mark Salyzyn501c3732017-03-10 14:31:54 -0800274 inline const uid_t& getKey() const {
275 return uid;
276 }
277 inline const uid_t& getUid() const {
278 return getKey();
279 }
280 inline const pid_t& getPid() const {
281 return pid;
282 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800283
Mark Salyzyn501c3732017-03-10 14:31:54 -0800284 inline void add(LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800285 if (pid != element->getPid()) {
286 pid = -1;
287 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800288 EntryBaseDropped::add(element);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800289 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700290
Mark Salyzyn501c3732017-03-10 14:31:54 -0800291 std::string formatHeader(const std::string& name, log_id_t id) const;
292 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700293};
294
295namespace android {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700296uid_t pidToUid(pid_t pid);
297}
298
299struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700300 const pid_t pid;
301 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800302 char* name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700303
Mark Salyzyn501c3732017-03-10 14:31:54 -0800304 explicit PidEntry(pid_t pid)
305 : EntryBaseDropped(),
306 pid(pid),
307 uid(android::pidToUid(pid)),
308 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700309 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800310 explicit PidEntry(LogBufferElement* element)
311 : EntryBaseDropped(element),
312 pid(element->getPid()),
313 uid(element->getUid()),
314 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700315 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800316 PidEntry(const PidEntry& element)
317 : EntryBaseDropped(element),
318 pid(element.pid),
319 uid(element.uid),
320 name(element.name ? strdup(element.name) : NULL) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700321 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800322 ~PidEntry() {
323 free(name);
324 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700325
Mark Salyzyn501c3732017-03-10 14:31:54 -0800326 const pid_t& getKey() const {
327 return pid;
328 }
329 const pid_t& getPid() const {
330 return getKey();
331 }
332 const uid_t& getUid() const {
333 return uid;
334 }
335 const char* getName() const {
336 return name;
337 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700338
Mark Salyzyn758058f2015-08-21 16:44:30 -0700339 inline void add(pid_t newPid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800340 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700341 free(name);
342 name = NULL;
343 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700344 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700345 name = android::pidToName(newPid);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700346 }
347 }
348
Mark Salyzyn501c3732017-03-10 14:31:54 -0800349 inline void add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700350 uid_t incomingUid = element->getUid();
351 if (getUid() != incomingUid) {
352 uid = incomingUid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700353 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700354 name = android::pidToName(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700355 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700356 add(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700357 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700358 EntryBaseDropped::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700359 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700360
Mark Salyzyn501c3732017-03-10 14:31:54 -0800361 std::string formatHeader(const std::string& name, log_id_t id) const;
362 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700363};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700364
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700365struct TidEntry : public EntryBaseDropped {
366 const pid_t tid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800367 pid_t pid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700368 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800369 char* name;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700370
Mark Salyzyn501c3732017-03-10 14:31:54 -0800371 TidEntry(pid_t tid, pid_t pid)
372 : EntryBaseDropped(),
373 tid(tid),
374 pid(pid),
375 uid(android::pidToUid(tid)),
376 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700377 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800378 explicit TidEntry(LogBufferElement* element)
379 : EntryBaseDropped(element),
380 tid(element->getTid()),
381 pid(element->getPid()),
382 uid(element->getUid()),
383 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700384 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800385 TidEntry(const TidEntry& element)
386 : EntryBaseDropped(element),
387 tid(element.tid),
388 pid(element.pid),
389 uid(element.uid),
390 name(element.name ? strdup(element.name) : NULL) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700391 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800392 ~TidEntry() {
393 free(name);
394 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700395
Mark Salyzyn501c3732017-03-10 14:31:54 -0800396 const pid_t& getKey() const {
397 return tid;
398 }
399 const pid_t& getTid() const {
400 return getKey();
401 }
402 const pid_t& getPid() const {
403 return pid;
404 }
405 const uid_t& getUid() const {
406 return uid;
407 }
408 const char* getName() const {
409 return name;
410 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700411
Mark Salyzyn758058f2015-08-21 16:44:30 -0700412 inline void add(pid_t incomingTid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800413 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700414 free(name);
415 name = NULL;
416 }
417 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700418 name = android::tidToName(incomingTid);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700419 }
420 }
421
Mark Salyzyn501c3732017-03-10 14:31:54 -0800422 inline void add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700423 uid_t incomingUid = element->getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800424 pid_t incomingPid = element->getPid();
425 if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700426 uid = incomingUid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800427 pid = incomingPid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700428 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700429 name = android::tidToName(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700430 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700431 add(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700432 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700433 EntryBaseDropped::add(element);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700434 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700435
Mark Salyzyn501c3732017-03-10 14:31:54 -0800436 std::string formatHeader(const std::string& name, log_id_t id) const;
437 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700438};
439
Mark Salyzyn6a066942016-07-14 15:34:30 -0700440struct TagEntry : public EntryBaseDropped {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700441 const uint32_t tag;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800442 pid_t pid;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700443 uid_t uid;
444
Mark Salyzyn501c3732017-03-10 14:31:54 -0800445 explicit TagEntry(LogBufferElement* element)
446 : EntryBaseDropped(element),
447 tag(element->getTag()),
448 pid(element->getPid()),
449 uid(element->getUid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700450 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700451
Mark Salyzyn501c3732017-03-10 14:31:54 -0800452 const uint32_t& getKey() const {
453 return tag;
454 }
455 const pid_t& getPid() const {
456 return pid;
457 }
458 const uid_t& getUid() const {
459 return uid;
460 }
461 const char* getName() const {
462 return android::tagToName(tag);
463 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700464
Mark Salyzyn501c3732017-03-10 14:31:54 -0800465 inline void add(LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800466 if (uid != element->getUid()) {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700467 uid = -1;
468 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800469 if (pid != element->getPid()) {
470 pid = -1;
471 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800472 EntryBaseDropped::add(element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700473 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700474
Mark Salyzyn501c3732017-03-10 14:31:54 -0800475 std::string formatHeader(const std::string& name, log_id_t id) const;
476 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700477};
478
Mark Salyzyn6a066942016-07-14 15:34:30 -0700479template <typename TEntry>
480class LogFindWorst {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800481 std::unique_ptr<const TEntry* []> sorted;
Mark Salyzyn6a066942016-07-14 15:34:30 -0700482
Mark Salyzyn501c3732017-03-10 14:31:54 -0800483 public:
484 explicit LogFindWorst(std::unique_ptr<const TEntry* []>&& sorted)
485 : sorted(std::move(sorted)) {
486 }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700487
Mark Salyzyn501c3732017-03-10 14:31:54 -0800488 void findWorst(int& worst, size_t& worst_sizes, size_t& second_worst_sizes,
489 size_t threshold) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700490 if (sorted.get() && sorted[0] && sorted[1]) {
491 worst_sizes = sorted[0]->getSizes();
492 if ((worst_sizes > threshold)
493 // Allow time horizon to extend roughly tenfold, assume
494 // average entry length is 100 characters.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800495 && (worst_sizes > (10 * sorted[0]->getDropped()))) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700496 worst = sorted[0]->getKey();
497 second_worst_sizes = sorted[1]->getSizes();
498 if (second_worst_sizes < threshold) {
499 second_worst_sizes = threshold;
500 }
501 }
502 }
503 }
504
Mark Salyzyn501c3732017-03-10 14:31:54 -0800505 void findWorst(int& worst, size_t worst_sizes, size_t& second_worst_sizes) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700506 if (sorted.get() && sorted[0] && sorted[1]) {
507 worst = sorted[0]->getKey();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800508 second_worst_sizes =
509 worst_sizes - sorted[0]->getSizes() + sorted[1]->getSizes();
Mark Salyzyn6a066942016-07-14 15:34:30 -0700510 }
511 }
512};
513
Mark Salyzyn34facab2014-02-06 14:48:50 -0800514// Log Statistics
515class LogStatistics {
Mark Salyzync723df82015-08-24 11:08:00 -0700516 friend UidEntry;
517
Mark Salyzyn34facab2014-02-06 14:48:50 -0800518 size_t mSizes[LOG_ID_MAX];
519 size_t mElements[LOG_ID_MAX];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700520 size_t mDroppedElements[LOG_ID_MAX];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700521 size_t mSizesTotal[LOG_ID_MAX];
522 size_t mElementsTotal[LOG_ID_MAX];
Mark Salyzyn32962912016-09-12 10:29:17 -0700523 static size_t SizesTotal;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700524 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800525
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700526 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700527 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700528 uidTable_t uidTable[LOG_ID_MAX];
Mark Salyzyne457b742014-02-19 17:18:31 -0800529
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700530 // pid of system to size list
531 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
532 pidSystemTable_t pidSystemTable[LOG_ID_MAX];
533
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700534 // pid to uid list
535 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
536 pidTable_t pidTable;
537
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700538 // tid to uid list
539 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
540 tidTable_t tidTable;
541
Mark Salyzyn344bff42015-04-13 14:24:45 -0700542 // tag list
543 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
544 tagTable_t tagTable;
545
Mark Salyzyn083b0372015-12-04 10:59:45 -0800546 // security tag list
547 tagTable_t securityTagTable;
548
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700549 size_t sizeOf() const {
550 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700551 tagTable.sizeOf() + securityTagTable.sizeOf() +
552 (pidTable.size() * sizeof(pidTable_t::iterator)) +
553 (tagTable.size() * sizeof(tagTable_t::iterator));
Mark Salyzyn501c3732017-03-10 14:31:54 -0800554 for (auto it : pidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700555 const char* name = it.second.getName();
556 if (name) size += strlen(name) + 1;
557 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800558 for (auto it : tidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700559 const char* name = it.second.getName();
560 if (name) size += strlen(name) + 1;
561 }
562 log_id_for_each(id) {
563 size += uidTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700564 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700565 size += pidSystemTable[id].sizeOf();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800566 size +=
567 pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700568 }
569 return size;
570 }
571
Mark Salyzyn501c3732017-03-10 14:31:54 -0800572 public:
Mark Salyzyn34facab2014-02-06 14:48:50 -0800573 LogStatistics();
574
Mark Salyzyn501c3732017-03-10 14:31:54 -0800575 void enableStatistics() {
576 enable = true;
577 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800578
Mark Salyzyn501c3732017-03-10 14:31:54 -0800579 void add(LogBufferElement* entry);
580 void subtract(LogBufferElement* entry);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700581 // entry->setDropped(1) must follow this call
Mark Salyzyn501c3732017-03-10 14:31:54 -0800582 void drop(LogBufferElement* entry);
Mark Salyzynaaad42f2015-09-30 07:40:09 -0700583 // Correct for coalescing two entries referencing dropped content
Mark Salyzyn501c3732017-03-10 14:31:54 -0800584 void erase(LogBufferElement* element) {
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700585 log_id_t log_id = element->getLogId();
586 --mElements[log_id];
587 --mDroppedElements[log_id];
588 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800589
Mark Salyzyn6a066942016-07-14 15:34:30 -0700590 LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
591 return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700592 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800593 LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len,
594 log_id id) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700595 return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
596 }
597 LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
598 return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700599 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800600
601 // fast track current value by id only
Mark Salyzyn501c3732017-03-10 14:31:54 -0800602 size_t sizes(log_id_t id) const {
603 return mSizes[id];
604 }
605 size_t elements(log_id_t id) const {
606 return mElements[id];
607 }
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700608 size_t realElements(log_id_t id) const {
609 return mElements[id] - mDroppedElements[id];
610 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800611 size_t sizesTotal(log_id_t id) const {
612 return mSizesTotal[id];
613 }
614 size_t elementsTotal(log_id_t id) const {
615 return mElementsTotal[id];
616 }
617 static size_t sizesTotal() {
618 return SizesTotal;
619 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800620
Mark Salyzynee3b8382015-12-17 09:58:43 -0800621 std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
Mark Salyzyn9a038632014-04-07 07:05:40 -0700622
Mark Salyzyned777e92015-06-24 16:22:54 -0700623 // helper (must be locked directly or implicitly by mLogElementsLock)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800624 const char* pidToName(pid_t pid) const;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700625 uid_t pidToUid(pid_t pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800626 const char* uidToName(uid_t uid) const;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800627};
628
Mark Salyzyn501c3732017-03-10 14:31:54 -0800629#endif // _LOGD_LOG_STATISTICS_H__