Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 1 | /* |
| 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 Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 20 | #include <memory> |
| 21 | #include <stdlib.h> |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 22 | #include <sys/types.h> |
| 23 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 24 | #include <algorithm> // std::max |
| 25 | #include <string> // std::string |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 26 | #include <unordered_map> |
| 27 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 28 | #include <base/stringprintf.h> |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 29 | #include <log/log.h> |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 30 | #include <private/android_filesystem_config.h> |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 31 | |
| 32 | #include "LogBufferElement.h" |
Mark Salyzyn | 5ac5c6b | 2015-08-28 08:02:59 -0700 | [diff] [blame] | 33 | #include "LogUtils.h" |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 34 | |
| 35 | #define log_id_for_each(i) \ |
| 36 | for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1)) |
| 37 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 38 | class LogStatistics; |
| 39 | |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 40 | template <typename TKey, typename TEntry> |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 41 | class LogHashtable { |
| 42 | |
| 43 | std::unordered_map<TKey, TEntry> map; |
| 44 | |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 45 | public: |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 46 | |
| 47 | typedef typename std::unordered_map<TKey, TEntry>::iterator iterator; |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 48 | typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator; |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 49 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 50 | std::unique_ptr<const TEntry *[]> sort(size_t len) const { |
| 51 | if (!len) { |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 52 | std::unique_ptr<const TEntry *[]> sorted(NULL); |
| 53 | return sorted; |
| 54 | } |
| 55 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 56 | const TEntry **retval = new const TEntry* [len]; |
| 57 | memset(retval, 0, sizeof(*retval) * len); |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 58 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 59 | for(const_iterator it = map.begin(); it != map.end(); ++it) { |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 60 | const TEntry &entry = it->second; |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 61 | size_t sizes = entry.getSizes(); |
| 62 | ssize_t index = len - 1; |
| 63 | while ((!retval[index] || (sizes > retval[index]->getSizes())) |
| 64 | && (--index >= 0)) |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 65 | ; |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 66 | if (++index < (ssize_t)len) { |
| 67 | size_t num = len - index - 1; |
| 68 | if (num) { |
| 69 | memmove(&retval[index + 1], &retval[index], |
| 70 | num * sizeof(retval[0])); |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 71 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 72 | retval[index] = &entry; |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 73 | } |
| 74 | } |
| 75 | std::unique_ptr<const TEntry *[]> sorted(retval); |
| 76 | return sorted; |
| 77 | } |
| 78 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 79 | inline iterator add(TKey key, LogBufferElement *element) { |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 80 | iterator it = map.find(key); |
| 81 | if (it == map.end()) { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 82 | it = map.insert(std::make_pair(key, TEntry(element))).first; |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 83 | } else { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 84 | it->second.add(element); |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 85 | } |
| 86 | return it; |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 87 | } |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 88 | |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 89 | inline iterator add(TKey key) { |
| 90 | iterator it = map.find(key); |
| 91 | if (it == map.end()) { |
| 92 | it = map.insert(std::make_pair(key, TEntry(key))).first; |
| 93 | } else { |
| 94 | it->second.add(key); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 95 | } |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 96 | return it; |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 97 | } |
| 98 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 99 | void subtract(TKey key, LogBufferElement *element) { |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 100 | iterator it = map.find(key); |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 101 | if ((it != map.end()) && it->second.subtract(element)) { |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 102 | map.erase(it); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 103 | } |
| 104 | } |
| 105 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 106 | inline void drop(TKey key, LogBufferElement *element) { |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 107 | iterator it = map.find(key); |
| 108 | if (it != map.end()) { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 109 | it->second.drop(element); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 110 | } |
| 111 | } |
| 112 | |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 113 | inline iterator begin() { return map.begin(); } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 114 | inline const_iterator begin() const { return map.begin(); } |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 115 | inline iterator end() { return map.end(); } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 116 | inline const_iterator end() const { return map.end(); } |
Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 117 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 118 | std::string format( |
| 119 | const LogStatistics &stat, |
| 120 | uid_t uid, |
| 121 | const std::string &name = std::string(""), |
| 122 | log_id_t id = LOG_ID_MAX) const { |
| 123 | static const size_t maximum_sorted_entries = 32; |
| 124 | std::string output; |
| 125 | std::unique_ptr<const TEntry *[]> sorted = sort(maximum_sorted_entries); |
| 126 | |
| 127 | if (!sorted.get()) { |
| 128 | return output; |
| 129 | } |
| 130 | bool headerPrinted = false; |
| 131 | for (size_t index = 0; index < maximum_sorted_entries; ++index) { |
| 132 | const TEntry *entry = sorted[index]; |
| 133 | if (!entry) { |
| 134 | break; |
| 135 | } |
| 136 | if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) { |
| 137 | break; |
| 138 | } |
| 139 | if ((uid != AID_ROOT) && (uid != entry->getUid())) { |
| 140 | continue; |
| 141 | } |
| 142 | if (!headerPrinted) { |
| 143 | output += "\n\n"; |
| 144 | output += entry->formatHeader(name, id); |
| 145 | headerPrinted = true; |
| 146 | } |
| 147 | output += entry->format(stat, id); |
| 148 | } |
| 149 | return output; |
| 150 | } |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 151 | }; |
| 152 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 153 | namespace EntryBaseConstants { |
| 154 | static constexpr size_t pruned_len = 14; |
| 155 | static constexpr size_t total_len = 80; |
| 156 | } |
| 157 | |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 158 | struct EntryBase { |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 159 | size_t size; |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 160 | |
| 161 | EntryBase():size(0) { } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 162 | EntryBase(LogBufferElement *element):size(element->getMsgLen()) { } |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 163 | |
| 164 | size_t getSizes() const { return size; } |
| 165 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 166 | inline void add(LogBufferElement *element) { size += element->getMsgLen(); } |
| 167 | inline bool subtract(LogBufferElement *element) { |
| 168 | size -= element->getMsgLen(); |
| 169 | return !size; |
| 170 | } |
| 171 | |
| 172 | static std::string formatLine( |
| 173 | const std::string &name, |
| 174 | const std::string &size, |
| 175 | const std::string &pruned) { |
| 176 | ssize_t drop_len = std::max(pruned.length() + 1, |
| 177 | EntryBaseConstants::pruned_len); |
| 178 | ssize_t size_len = std::max(size.length() + 1, |
| 179 | EntryBaseConstants::total_len |
| 180 | - name.length() - drop_len - 1); |
| 181 | |
| 182 | if (pruned.length()) { |
| 183 | return android::base::StringPrintf("%s%*s%*s\n", name.c_str(), |
| 184 | (int)size_len, size.c_str(), |
| 185 | (int)drop_len, pruned.c_str()); |
| 186 | } else { |
| 187 | return android::base::StringPrintf("%s%*s\n", name.c_str(), |
| 188 | (int)size_len, size.c_str()); |
| 189 | } |
| 190 | } |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 191 | }; |
| 192 | |
| 193 | struct EntryBaseDropped : public EntryBase { |
Mark Salyzyn | ab0dcf6 | 2015-03-16 12:04:09 -0700 | [diff] [blame] | 194 | size_t dropped; |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 195 | |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 196 | EntryBaseDropped():dropped(0) { } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 197 | EntryBaseDropped(LogBufferElement *element): |
| 198 | EntryBase(element), |
| 199 | dropped(element->getDropped()){ |
| 200 | } |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 201 | |
Mark Salyzyn | ab0dcf6 | 2015-03-16 12:04:09 -0700 | [diff] [blame] | 202 | size_t getDropped() const { return dropped; } |
| 203 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 204 | inline void add(LogBufferElement *element) { |
| 205 | dropped += element->getDropped(); |
| 206 | EntryBase::add(element); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 207 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 208 | inline bool subtract(LogBufferElement *element) { |
| 209 | dropped -= element->getDropped(); |
| 210 | return EntryBase::subtract(element) && !dropped; |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 211 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 212 | inline void drop(LogBufferElement *element) { |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 213 | dropped += 1; |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 214 | EntryBase::subtract(element); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 215 | } |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 216 | }; |
| 217 | |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 218 | struct UidEntry : public EntryBaseDropped { |
| 219 | const uid_t uid; |
| 220 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 221 | UidEntry(LogBufferElement *element): |
| 222 | EntryBaseDropped(element), |
| 223 | uid(element->getUid()) { |
| 224 | } |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 225 | |
| 226 | inline const uid_t&getKey() const { return uid; } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 227 | inline const uid_t&getUid() const { return uid; } |
| 228 | |
| 229 | std::string formatHeader(const std::string &name, log_id_t id) const; |
| 230 | std::string format(const LogStatistics &stat, log_id_t id) const; |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 231 | }; |
| 232 | |
| 233 | namespace android { |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 234 | uid_t pidToUid(pid_t pid); |
| 235 | } |
| 236 | |
| 237 | struct PidEntry : public EntryBaseDropped { |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 238 | const pid_t pid; |
| 239 | uid_t uid; |
| 240 | char *name; |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 241 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 242 | PidEntry(pid_t pid): |
| 243 | EntryBaseDropped(), |
| 244 | pid(pid), |
| 245 | uid(android::pidToUid(pid)), |
| 246 | name(android::pidToName(pid)) { |
| 247 | } |
| 248 | PidEntry(LogBufferElement *element): |
| 249 | EntryBaseDropped(element), |
| 250 | pid(element->getPid()), |
| 251 | uid(element->getUid()), |
| 252 | name(android::pidToName(pid)) { |
| 253 | } |
| 254 | PidEntry(const PidEntry &element): |
| 255 | EntryBaseDropped(element), |
| 256 | pid(element.pid), |
| 257 | uid(element.uid), |
| 258 | name(element.name ? strdup(element.name) : NULL) { |
| 259 | } |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 260 | ~PidEntry() { free(name); } |
| 261 | |
| 262 | const pid_t&getKey() const { return pid; } |
| 263 | const uid_t&getUid() const { return uid; } |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 264 | const char*getName() const { return name; } |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 265 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 266 | inline void add(pid_t newPid) { |
Mark Salyzyn | ddda212 | 2015-10-02 09:22:52 -0700 | [diff] [blame] | 267 | if (name && !fast<strncmp>(name, "zygote", 6)) { |
Mark Salyzyn | aa43ae2 | 2015-04-20 10:27:38 -0700 | [diff] [blame] | 268 | free(name); |
| 269 | name = NULL; |
| 270 | } |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 271 | if (!name) { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 272 | name = android::pidToName(newPid); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 273 | } |
| 274 | } |
| 275 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 276 | inline void add(LogBufferElement *element) { |
| 277 | uid_t incomingUid = element->getUid(); |
| 278 | if (getUid() != incomingUid) { |
| 279 | uid = incomingUid; |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 280 | free(name); |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 281 | name = android::pidToName(element->getPid()); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 282 | } else { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 283 | add(element->getPid()); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 284 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 285 | EntryBaseDropped::add(element); |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 286 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 287 | |
| 288 | std::string formatHeader(const std::string &name, log_id_t id) const; |
| 289 | std::string format(const LogStatistics &stat, log_id_t id) const; |
Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 290 | }; |
Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 291 | |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 292 | struct TidEntry : public EntryBaseDropped { |
| 293 | const pid_t tid; |
| 294 | uid_t uid; |
| 295 | char *name; |
| 296 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 297 | TidEntry(pid_t tid): |
| 298 | EntryBaseDropped(), |
| 299 | tid(tid), |
| 300 | uid(android::pidToUid(tid)), |
| 301 | name(android::tidToName(tid)) { |
| 302 | } |
| 303 | TidEntry(LogBufferElement *element): |
| 304 | EntryBaseDropped(element), |
| 305 | tid(element->getTid()), |
| 306 | uid(element->getUid()), |
| 307 | name(android::tidToName(tid)) { |
| 308 | } |
| 309 | TidEntry(const TidEntry &element): |
| 310 | EntryBaseDropped(element), |
| 311 | tid(element.tid), |
| 312 | uid(element.uid), |
| 313 | name(element.name ? strdup(element.name) : NULL) { |
| 314 | } |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 315 | ~TidEntry() { free(name); } |
| 316 | |
| 317 | const pid_t&getKey() const { return tid; } |
| 318 | const uid_t&getUid() const { return uid; } |
| 319 | const char*getName() const { return name; } |
| 320 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 321 | inline void add(pid_t incomingTid) { |
Mark Salyzyn | ddda212 | 2015-10-02 09:22:52 -0700 | [diff] [blame] | 322 | if (name && !fast<strncmp>(name, "zygote", 6)) { |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 323 | free(name); |
| 324 | name = NULL; |
| 325 | } |
| 326 | if (!name) { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 327 | name = android::tidToName(incomingTid); |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 328 | } |
| 329 | } |
| 330 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 331 | inline void add(LogBufferElement *element) { |
| 332 | uid_t incomingUid = element->getUid(); |
| 333 | if (getUid() != incomingUid) { |
| 334 | uid = incomingUid; |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 335 | free(name); |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 336 | name = android::tidToName(element->getTid()); |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 337 | } else { |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 338 | add(element->getTid()); |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 339 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 340 | EntryBaseDropped::add(element); |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 341 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 342 | |
| 343 | std::string formatHeader(const std::string &name, log_id_t id) const; |
| 344 | std::string format(const LogStatistics &stat, log_id_t id) const; |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 345 | }; |
| 346 | |
Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 347 | struct TagEntry : public EntryBase { |
| 348 | const uint32_t tag; |
| 349 | uid_t uid; |
| 350 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 351 | TagEntry(LogBufferElement *element): |
| 352 | EntryBase(element), |
| 353 | tag(element->getTag()), |
| 354 | uid(element->getUid()) { |
| 355 | } |
Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 356 | |
| 357 | const uint32_t&getKey() const { return tag; } |
| 358 | const uid_t&getUid() const { return uid; } |
| 359 | const char*getName() const { return android::tagToName(tag); } |
| 360 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 361 | inline void add(LogBufferElement *element) { |
| 362 | uid_t incomingUid = element->getUid(); |
| 363 | if (uid != incomingUid) { |
Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 364 | uid = -1; |
| 365 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 366 | EntryBase::add(element); |
Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 367 | } |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 368 | |
| 369 | std::string formatHeader(const std::string &name, log_id_t id) const; |
| 370 | std::string format(const LogStatistics &stat, log_id_t id) const; |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 371 | }; |
| 372 | |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 373 | // Log Statistics |
| 374 | class LogStatistics { |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 375 | size_t mSizes[LOG_ID_MAX]; |
| 376 | size_t mElements[LOG_ID_MAX]; |
Mark Salyzyn | 58b8be8 | 2015-09-30 07:40:09 -0700 | [diff] [blame^] | 377 | size_t mDroppedElements[LOG_ID_MAX]; |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 378 | size_t mSizesTotal[LOG_ID_MAX]; |
| 379 | size_t mElementsTotal[LOG_ID_MAX]; |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 380 | bool enable; |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 381 | |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 382 | // uid to size list |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 383 | typedef LogHashtable<uid_t, UidEntry> uidTable_t; |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 384 | uidTable_t uidTable[LOG_ID_MAX]; |
Mark Salyzyn | e457b74 | 2014-02-19 17:18:31 -0800 | [diff] [blame] | 385 | |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 386 | // pid to uid list |
| 387 | typedef LogHashtable<pid_t, PidEntry> pidTable_t; |
| 388 | pidTable_t pidTable; |
| 389 | |
Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 390 | // tid to uid list |
| 391 | typedef LogHashtable<pid_t, TidEntry> tidTable_t; |
| 392 | tidTable_t tidTable; |
| 393 | |
Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 394 | // tag list |
| 395 | typedef LogHashtable<uint32_t, TagEntry> tagTable_t; |
| 396 | tagTable_t tagTable; |
| 397 | |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 398 | public: |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 399 | LogStatistics(); |
| 400 | |
Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 401 | void enableStatistics() { enable = true; } |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 402 | |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 403 | void add(LogBufferElement *entry); |
| 404 | void subtract(LogBufferElement *entry); |
Mark Salyzyn | ab0dcf6 | 2015-03-16 12:04:09 -0700 | [diff] [blame] | 405 | // entry->setDropped(1) must follow this call |
| 406 | void drop(LogBufferElement *entry); |
Mark Salyzyn | aaad42f | 2015-09-30 07:40:09 -0700 | [diff] [blame] | 407 | // Correct for coalescing two entries referencing dropped content |
Mark Salyzyn | 58b8be8 | 2015-09-30 07:40:09 -0700 | [diff] [blame^] | 408 | void erase(LogBufferElement *element) { |
| 409 | log_id_t log_id = element->getLogId(); |
| 410 | --mElements[log_id]; |
| 411 | --mDroppedElements[log_id]; |
| 412 | } |
Mark Salyzyn | e457b74 | 2014-02-19 17:18:31 -0800 | [diff] [blame] | 413 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 414 | std::unique_ptr<const UidEntry *[]> sort(size_t len, log_id id) { |
| 415 | return uidTable[id].sort(len); |
| 416 | } |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 417 | |
| 418 | // fast track current value by id only |
| 419 | size_t sizes(log_id_t id) const { return mSizes[id]; } |
| 420 | size_t elements(log_id_t id) const { return mElements[id]; } |
Mark Salyzyn | 58b8be8 | 2015-09-30 07:40:09 -0700 | [diff] [blame^] | 421 | size_t realElements(log_id_t id) const { |
| 422 | return mElements[id] - mDroppedElements[id]; |
| 423 | } |
Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 424 | size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; } |
| 425 | size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; } |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 426 | |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 427 | std::string format(uid_t uid, unsigned int logMask) const; |
Mark Salyzyn | 9a03863 | 2014-04-07 07:05:40 -0700 | [diff] [blame] | 428 | |
Mark Salyzyn | ed777e9 | 2015-06-24 16:22:54 -0700 | [diff] [blame] | 429 | // helper (must be locked directly or implicitly by mLogElementsLock) |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 430 | const char *pidToName(pid_t pid) const; |
Mark Salyzyn | 4ba0387 | 2014-04-07 07:15:33 -0700 | [diff] [blame] | 431 | uid_t pidToUid(pid_t pid); |
Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 432 | const char *uidToName(uid_t uid) const; |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 433 | }; |
| 434 | |
| 435 | #endif // _LOGD_LOG_STATISTICS_H__ |