| 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 | b545e1c | 2016-12-19 14:51:15 -0800 | [diff] [blame] | 20 | #include <ctype.h> | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 21 | #include <inttypes.h> | 
 | 22 | #include <stdint.h> | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 23 | #include <stdlib.h> | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 24 | #include <string.h> | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 25 | #include <sys/types.h> | 
 | 26 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 27 | #include <algorithm>  // std::max | 
| Mark Salyzyn | b545e1c | 2016-12-19 14:51:15 -0800 | [diff] [blame] | 28 | #include <memory> | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 29 | #include <string> | 
 | 30 | #include <string_view> | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 31 | #include <unordered_map> | 
 | 32 |  | 
| Elliott Hughes | 4f71319 | 2015-12-04 22:00:26 -0800 | [diff] [blame] | 33 | #include <android-base/stringprintf.h> | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 34 | #include <android/log.h> | 
| Mark Salyzyn | 03bb759 | 2017-04-14 09:46:57 -0700 | [diff] [blame] | 35 | #include <log/log_time.h> | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 36 | #include <private/android_filesystem_config.h> | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 37 | #include <utils/FastStrcmp.h> | 
| Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 38 |  | 
 | 39 | #include "LogBufferElement.h" | 
| Mark Salyzyn | 5ac5c6b | 2015-08-28 08:02:59 -0700 | [diff] [blame] | 40 | #include "LogUtils.h" | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 41 |  | 
 | 42 | #define log_id_for_each(i) \ | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 43 |     for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1)) | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 44 |  | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 45 | class LogStatistics; | 
 | 46 |  | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 47 | template <typename TKey, typename TEntry> | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 48 | class LogHashtable { | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 49 |     std::unordered_map<TKey, TEntry> map; | 
 | 50 |  | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 51 |     size_t bucket_size() const { | 
 | 52 |         size_t count = 0; | 
 | 53 |         for (size_t idx = 0; idx < map.bucket_count(); ++idx) { | 
 | 54 |             size_t bucket_size = map.bucket_size(idx); | 
 | 55 |             if (bucket_size == 0) bucket_size = 1; | 
 | 56 |             count += bucket_size; | 
 | 57 |         } | 
 | 58 |         float load_factor = map.max_load_factor(); | 
 | 59 |         if (load_factor < 1.0) return count; | 
 | 60 |         return count * load_factor; | 
 | 61 |     } | 
 | 62 |  | 
 | 63 |     static const size_t unordered_map_per_entry_overhead = sizeof(void*); | 
 | 64 |     static const size_t unordered_map_bucket_overhead = sizeof(void*); | 
 | 65 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 66 |    public: | 
 | 67 |     size_t size() const { | 
 | 68 |         return map.size(); | 
 | 69 |     } | 
| Mark Salyzyn | b067229 | 2016-10-06 10:09:24 -0700 | [diff] [blame] | 70 |  | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 71 |     // Estimate unordered_map memory usage. | 
 | 72 |     size_t sizeOf() const { | 
 | 73 |         return sizeof(*this) + | 
| Mark Salyzyn | b067229 | 2016-10-06 10:09:24 -0700 | [diff] [blame] | 74 |                (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) + | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 75 |                (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead); | 
 | 76 |     } | 
 | 77 |  | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 78 |     typedef typename std::unordered_map<TKey, TEntry>::iterator iterator; | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 79 |     typedef | 
 | 80 |         typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator; | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 81 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 82 |     std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid, | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 83 |                                            size_t len) const { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 84 |         if (!len) { | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 85 |             std::unique_ptr<const TEntry* []> sorted(nullptr); | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 86 |             return sorted; | 
 | 87 |         } | 
 | 88 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 89 |         const TEntry** retval = new const TEntry*[len]; | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 90 |         memset(retval, 0, sizeof(*retval) * len); | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 91 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 92 |         for (const_iterator it = map.begin(); it != map.end(); ++it) { | 
 | 93 |             const TEntry& entry = it->second; | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 94 |  | 
 | 95 |             if ((uid != AID_ROOT) && (uid != entry.getUid())) { | 
 | 96 |                 continue; | 
 | 97 |             } | 
 | 98 |             if (pid && entry.getPid() && (pid != entry.getPid())) { | 
 | 99 |                 continue; | 
 | 100 |             } | 
 | 101 |  | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 102 |             size_t sizes = entry.getSizes(); | 
 | 103 |             ssize_t index = len - 1; | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 104 |             while ((!retval[index] || (sizes > retval[index]->getSizes())) && | 
 | 105 |                    (--index >= 0)) | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 106 |                 ; | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 107 |             if (++index < (ssize_t)len) { | 
 | 108 |                 size_t num = len - index - 1; | 
 | 109 |                 if (num) { | 
 | 110 |                     memmove(&retval[index + 1], &retval[index], | 
 | 111 |                             num * sizeof(retval[0])); | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 112 |                 } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 113 |                 retval[index] = &entry; | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 114 |             } | 
 | 115 |         } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 116 |         std::unique_ptr<const TEntry* []> sorted(retval); | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 117 |         return sorted; | 
 | 118 |     } | 
 | 119 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 120 |     inline iterator add(const TKey& key, const LogBufferElement* element) { | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 121 |         iterator it = map.find(key); | 
 | 122 |         if (it == map.end()) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 123 |             it = map.insert(std::make_pair(key, TEntry(element))).first; | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 124 |         } else { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 125 |             it->second.add(element); | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 126 |         } | 
 | 127 |         return it; | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 128 |     } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 129 |  | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 130 |     inline iterator add(TKey key) { | 
 | 131 |         iterator it = map.find(key); | 
 | 132 |         if (it == map.end()) { | 
 | 133 |             it = map.insert(std::make_pair(key, TEntry(key))).first; | 
 | 134 |         } else { | 
 | 135 |             it->second.add(key); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 136 |         } | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 137 |         return it; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 138 |     } | 
 | 139 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 140 |     void subtract(TKey&& key, const LogBufferElement* element) { | 
 | 141 |         iterator it = map.find(std::move(key)); | 
 | 142 |         if ((it != map.end()) && it->second.subtract(element)) { | 
 | 143 |             map.erase(it); | 
 | 144 |         } | 
 | 145 |     } | 
 | 146 |  | 
 | 147 |     void subtract(const TKey& key, const LogBufferElement* element) { | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 148 |         iterator it = map.find(key); | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 149 |         if ((it != map.end()) && it->second.subtract(element)) { | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 150 |             map.erase(it); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 151 |         } | 
 | 152 |     } | 
 | 153 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 154 |     inline void drop(TKey key, const LogBufferElement* element) { | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 155 |         iterator it = map.find(key); | 
 | 156 |         if (it != map.end()) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 157 |             it->second.drop(element); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 158 |         } | 
 | 159 |     } | 
 | 160 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 161 |     inline iterator begin() { | 
 | 162 |         return map.begin(); | 
 | 163 |     } | 
 | 164 |     inline const_iterator begin() const { | 
 | 165 |         return map.begin(); | 
 | 166 |     } | 
 | 167 |     inline iterator end() { | 
 | 168 |         return map.end(); | 
 | 169 |     } | 
 | 170 |     inline const_iterator end() const { | 
 | 171 |         return map.end(); | 
 | 172 |     } | 
| Mark Salyzyn | 511338d | 2015-05-19 09:12:30 -0700 | [diff] [blame] | 173 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 174 |     std::string format(const LogStatistics& stat, uid_t uid, pid_t pid, | 
 | 175 |                        const std::string& name = std::string(""), | 
 | 176 |                        log_id_t id = LOG_ID_MAX) const { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 177 |         static const size_t maximum_sorted_entries = 32; | 
 | 178 |         std::string output; | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 179 |         std::unique_ptr<const TEntry* []> sorted = | 
 | 180 |             sort(uid, pid, maximum_sorted_entries); | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 181 |         if (!sorted.get()) { | 
 | 182 |             return output; | 
 | 183 |         } | 
 | 184 |         bool headerPrinted = false; | 
 | 185 |         for (size_t index = 0; index < maximum_sorted_entries; ++index) { | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 186 |             const TEntry* entry = sorted[index]; | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 187 |             if (!entry) { | 
 | 188 |                 break; | 
 | 189 |             } | 
 | 190 |             if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) { | 
 | 191 |                 break; | 
 | 192 |             } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 193 |             if (!headerPrinted) { | 
 | 194 |                 output += "\n\n"; | 
 | 195 |                 output += entry->formatHeader(name, id); | 
 | 196 |                 headerPrinted = true; | 
 | 197 |             } | 
 | 198 |             output += entry->format(stat, id); | 
 | 199 |         } | 
 | 200 |         return output; | 
 | 201 |     } | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 202 | }; | 
 | 203 |  | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 204 | namespace EntryBaseConstants { | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 205 | static constexpr size_t pruned_len = 14; | 
 | 206 | static constexpr size_t total_len = 80; | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 207 | } | 
 | 208 |  | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 209 | struct EntryBase { | 
| Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 210 |     size_t size; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 211 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 212 |     EntryBase() : size(0) { | 
 | 213 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 214 |     explicit EntryBase(const LogBufferElement* element) | 
 | 215 |         : size(element->getMsgLen()) { | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 216 |     } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 217 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 218 |     size_t getSizes() const { | 
 | 219 |         return size; | 
 | 220 |     } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 221 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 222 |     inline void add(const LogBufferElement* element) { | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 223 |         size += element->getMsgLen(); | 
 | 224 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 225 |     inline bool subtract(const LogBufferElement* element) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 226 |         size -= element->getMsgLen(); | 
 | 227 |         return !size; | 
 | 228 |     } | 
 | 229 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 230 |     static std::string formatLine(const std::string& name, | 
 | 231 |                                   const std::string& size, | 
 | 232 |                                   const std::string& pruned) { | 
 | 233 |         ssize_t drop_len = | 
 | 234 |             std::max(pruned.length() + 1, EntryBaseConstants::pruned_len); | 
 | 235 |         ssize_t size_len = | 
 | 236 |             std::max(size.length() + 1, EntryBaseConstants::total_len - | 
 | 237 |                                             name.length() - drop_len - 1); | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 238 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 239 |         std::string ret = android::base::StringPrintf( | 
 | 240 |             "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(), | 
 | 241 |             (int)drop_len, pruned.c_str()); | 
| Mark Salyzyn | b545e1c | 2016-12-19 14:51:15 -0800 | [diff] [blame] | 242 |         // remove any trailing spaces | 
 | 243 |         size_t pos = ret.size(); | 
 | 244 |         size_t len = 0; | 
 | 245 |         while (pos && isspace(ret[--pos])) ++len; | 
 | 246 |         if (len) ret.erase(pos + 1, len); | 
 | 247 |         return ret + "\n"; | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 248 |     } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 249 | }; | 
 | 250 |  | 
 | 251 | struct EntryBaseDropped : public EntryBase { | 
| Mark Salyzyn | ab0dcf6 | 2015-03-16 12:04:09 -0700 | [diff] [blame] | 252 |     size_t dropped; | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 253 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 254 |     EntryBaseDropped() : dropped(0) { | 
 | 255 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 256 |     explicit EntryBaseDropped(const LogBufferElement* element) | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 257 |         : EntryBase(element), dropped(element->getDropped()) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 258 |     } | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 259 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 260 |     size_t getDropped() const { | 
 | 261 |         return dropped; | 
 | 262 |     } | 
| Mark Salyzyn | ab0dcf6 | 2015-03-16 12:04:09 -0700 | [diff] [blame] | 263 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 264 |     inline void add(const LogBufferElement* element) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 265 |         dropped += element->getDropped(); | 
 | 266 |         EntryBase::add(element); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 267 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 268 |     inline bool subtract(const LogBufferElement* element) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 269 |         dropped -= element->getDropped(); | 
 | 270 |         return EntryBase::subtract(element) && !dropped; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 271 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 272 |     inline void drop(const LogBufferElement* element) { | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 273 |         dropped += 1; | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 274 |         EntryBase::subtract(element); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 275 |     } | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 276 | }; | 
 | 277 |  | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 278 | struct UidEntry : public EntryBaseDropped { | 
 | 279 |     const uid_t uid; | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 280 |     pid_t pid; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 281 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 282 |     explicit UidEntry(const LogBufferElement* element) | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 283 |         : EntryBaseDropped(element), | 
 | 284 |           uid(element->getUid()), | 
 | 285 |           pid(element->getPid()) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 286 |     } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 287 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 288 |     inline const uid_t& getKey() const { | 
 | 289 |         return uid; | 
 | 290 |     } | 
 | 291 |     inline const uid_t& getUid() const { | 
 | 292 |         return getKey(); | 
 | 293 |     } | 
 | 294 |     inline const pid_t& getPid() const { | 
 | 295 |         return pid; | 
 | 296 |     } | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 297 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 298 |     inline void add(const LogBufferElement* element) { | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 299 |         if (pid != element->getPid()) { | 
 | 300 |             pid = -1; | 
 | 301 |         } | 
| Mark Salyzyn | a2c0222 | 2016-12-13 10:31:29 -0800 | [diff] [blame] | 302 |         EntryBaseDropped::add(element); | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 303 |     } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 304 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 305 |     std::string formatHeader(const std::string& name, log_id_t id) const; | 
 | 306 |     std::string format(const LogStatistics& stat, log_id_t id) const; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 307 | }; | 
 | 308 |  | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 309 | struct PidEntry : public EntryBaseDropped { | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 310 |     const pid_t pid; | 
 | 311 |     uid_t uid; | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 312 |     char* name; | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 313 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 314 |     explicit PidEntry(pid_t pid) | 
 | 315 |         : EntryBaseDropped(), | 
 | 316 |           pid(pid), | 
 | 317 |           uid(android::pidToUid(pid)), | 
 | 318 |           name(android::pidToName(pid)) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 319 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 320 |     explicit PidEntry(const LogBufferElement* element) | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 321 |         : EntryBaseDropped(element), | 
 | 322 |           pid(element->getPid()), | 
 | 323 |           uid(element->getUid()), | 
 | 324 |           name(android::pidToName(pid)) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 325 |     } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 326 |     PidEntry(const PidEntry& element) | 
 | 327 |         : EntryBaseDropped(element), | 
 | 328 |           pid(element.pid), | 
 | 329 |           uid(element.uid), | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 330 |           name(element.name ? strdup(element.name) : nullptr) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 331 |     } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 332 |     ~PidEntry() { | 
 | 333 |         free(name); | 
 | 334 |     } | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 335 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 336 |     const pid_t& getKey() const { | 
 | 337 |         return pid; | 
 | 338 |     } | 
 | 339 |     const pid_t& getPid() const { | 
 | 340 |         return getKey(); | 
 | 341 |     } | 
 | 342 |     const uid_t& getUid() const { | 
 | 343 |         return uid; | 
 | 344 |     } | 
 | 345 |     const char* getName() const { | 
 | 346 |         return name; | 
 | 347 |     } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 348 |  | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 349 |     inline void add(pid_t newPid) { | 
| Mark Salyzyn | 0eeb06b | 2016-12-02 10:08:48 -0800 | [diff] [blame] | 350 |         if (name && !fastcmp<strncmp>(name, "zygote", 6)) { | 
| Mark Salyzyn | aa43ae2 | 2015-04-20 10:27:38 -0700 | [diff] [blame] | 351 |             free(name); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 352 |             name = nullptr; | 
| Mark Salyzyn | aa43ae2 | 2015-04-20 10:27:38 -0700 | [diff] [blame] | 353 |         } | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 354 |         if (!name) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 355 |             name = android::pidToName(newPid); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 356 |         } | 
 | 357 |     } | 
 | 358 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 359 |     inline void add(const LogBufferElement* element) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 360 |         uid_t incomingUid = element->getUid(); | 
 | 361 |         if (getUid() != incomingUid) { | 
 | 362 |             uid = incomingUid; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 363 |             free(name); | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 364 |             name = android::pidToName(element->getPid()); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 365 |         } else { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 366 |             add(element->getPid()); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 367 |         } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 368 |         EntryBaseDropped::add(element); | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 369 |     } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 370 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 371 |     std::string formatHeader(const std::string& name, log_id_t id) const; | 
 | 372 |     std::string format(const LogStatistics& stat, log_id_t id) const; | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 373 | }; | 
| Mark Salyzyn | 81b3eab | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 374 |  | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 375 | struct TidEntry : public EntryBaseDropped { | 
 | 376 |     const pid_t tid; | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 377 |     pid_t pid; | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 378 |     uid_t uid; | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 379 |     char* name; | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 380 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 381 |     TidEntry(pid_t tid, pid_t pid) | 
 | 382 |         : EntryBaseDropped(), | 
 | 383 |           tid(tid), | 
 | 384 |           pid(pid), | 
 | 385 |           uid(android::pidToUid(tid)), | 
 | 386 |           name(android::tidToName(tid)) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 387 |     } | 
| Mark Salyzyn | c4e4823 | 2017-05-04 13:54:46 -0700 | [diff] [blame] | 388 |     TidEntry(pid_t tid) | 
 | 389 |         : EntryBaseDropped(), | 
 | 390 |           tid(tid), | 
 | 391 |           pid(android::tidToPid(tid)), | 
 | 392 |           uid(android::pidToUid(tid)), | 
 | 393 |           name(android::tidToName(tid)) { | 
 | 394 |     } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 395 |     explicit TidEntry(const LogBufferElement* element) | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 396 |         : EntryBaseDropped(element), | 
 | 397 |           tid(element->getTid()), | 
 | 398 |           pid(element->getPid()), | 
 | 399 |           uid(element->getUid()), | 
 | 400 |           name(android::tidToName(tid)) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 401 |     } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 402 |     TidEntry(const TidEntry& element) | 
 | 403 |         : EntryBaseDropped(element), | 
 | 404 |           tid(element.tid), | 
 | 405 |           pid(element.pid), | 
 | 406 |           uid(element.uid), | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 407 |           name(element.name ? strdup(element.name) : nullptr) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 408 |     } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 409 |     ~TidEntry() { | 
 | 410 |         free(name); | 
 | 411 |     } | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 412 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 413 |     const pid_t& getKey() const { | 
 | 414 |         return tid; | 
 | 415 |     } | 
 | 416 |     const pid_t& getTid() const { | 
 | 417 |         return getKey(); | 
 | 418 |     } | 
 | 419 |     const pid_t& getPid() const { | 
 | 420 |         return pid; | 
 | 421 |     } | 
 | 422 |     const uid_t& getUid() const { | 
 | 423 |         return uid; | 
 | 424 |     } | 
 | 425 |     const char* getName() const { | 
 | 426 |         return name; | 
 | 427 |     } | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 428 |  | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 429 |     inline void add(pid_t incomingTid) { | 
| Mark Salyzyn | 0eeb06b | 2016-12-02 10:08:48 -0800 | [diff] [blame] | 430 |         if (name && !fastcmp<strncmp>(name, "zygote", 6)) { | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 431 |             free(name); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 432 |             name = nullptr; | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 433 |         } | 
 | 434 |         if (!name) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 435 |             name = android::tidToName(incomingTid); | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 436 |         } | 
 | 437 |     } | 
 | 438 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 439 |     inline void add(const LogBufferElement* element) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 440 |         uid_t incomingUid = element->getUid(); | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 441 |         pid_t incomingPid = element->getPid(); | 
 | 442 |         if ((getUid() != incomingUid) || (getPid() != incomingPid)) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 443 |             uid = incomingUid; | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 444 |             pid = incomingPid; | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 445 |             free(name); | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 446 |             name = android::tidToName(element->getTid()); | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 447 |         } else { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 448 |             add(element->getTid()); | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 449 |         } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 450 |         EntryBaseDropped::add(element); | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 451 |     } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 452 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 453 |     std::string formatHeader(const std::string& name, log_id_t id) const; | 
 | 454 |     std::string format(const LogStatistics& stat, log_id_t id) const; | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 455 | }; | 
 | 456 |  | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 457 | struct TagEntry : public EntryBaseDropped { | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 458 |     const uint32_t tag; | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 459 |     pid_t pid; | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 460 |     uid_t uid; | 
 | 461 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 462 |     explicit TagEntry(const LogBufferElement* element) | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 463 |         : EntryBaseDropped(element), | 
 | 464 |           tag(element->getTag()), | 
 | 465 |           pid(element->getPid()), | 
 | 466 |           uid(element->getUid()) { | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 467 |     } | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 468 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 469 |     const uint32_t& getKey() const { | 
 | 470 |         return tag; | 
 | 471 |     } | 
 | 472 |     const pid_t& getPid() const { | 
 | 473 |         return pid; | 
 | 474 |     } | 
 | 475 |     const uid_t& getUid() const { | 
 | 476 |         return uid; | 
 | 477 |     } | 
 | 478 |     const char* getName() const { | 
 | 479 |         return android::tagToName(tag); | 
 | 480 |     } | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 481 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 482 |     inline void add(const LogBufferElement* element) { | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 483 |         if (uid != element->getUid()) { | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 484 |             uid = -1; | 
 | 485 |         } | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 486 |         if (pid != element->getPid()) { | 
 | 487 |             pid = -1; | 
 | 488 |         } | 
| Mark Salyzyn | a2c0222 | 2016-12-13 10:31:29 -0800 | [diff] [blame] | 489 |         EntryBaseDropped::add(element); | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 490 |     } | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 491 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 492 |     std::string formatHeader(const std::string& name, log_id_t id) const; | 
 | 493 |     std::string format(const LogStatistics& stat, log_id_t id) const; | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 494 | }; | 
 | 495 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 496 | struct TagNameKey { | 
 | 497 |     std::string* alloc; | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 498 |     std::string_view name;  // Saves space if const char* | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 499 |  | 
 | 500 |     explicit TagNameKey(const LogBufferElement* element) | 
 | 501 |         : alloc(nullptr), name("", strlen("")) { | 
 | 502 |         if (element->isBinary()) { | 
 | 503 |             uint32_t tag = element->getTag(); | 
 | 504 |             if (tag) { | 
 | 505 |                 const char* cp = android::tagToName(tag); | 
 | 506 |                 if (cp) { | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 507 |                     name = std::string_view(cp, strlen(cp)); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 508 |                     return; | 
 | 509 |                 } | 
 | 510 |             } | 
 | 511 |             alloc = new std::string( | 
 | 512 |                 android::base::StringPrintf("[%" PRIu32 "]", tag)); | 
 | 513 |             if (!alloc) return; | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 514 |             name = std::string_view(alloc->c_str(), alloc->size()); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 515 |             return; | 
 | 516 |         } | 
 | 517 |         const char* msg = element->getMsg(); | 
 | 518 |         if (!msg) { | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 519 |             name = std::string_view("chatty", strlen("chatty")); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 520 |             return; | 
 | 521 |         } | 
 | 522 |         ++msg; | 
 | 523 |         unsigned short len = element->getMsgLen(); | 
 | 524 |         len = (len <= 1) ? 0 : strnlen(msg, len - 1); | 
 | 525 |         if (!len) { | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 526 |             name = std::string_view("<NULL>", strlen("<NULL>")); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 527 |             return; | 
 | 528 |         } | 
 | 529 |         alloc = new std::string(msg, len); | 
 | 530 |         if (!alloc) return; | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 531 |         name = std::string_view(alloc->c_str(), alloc->size()); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 532 |     } | 
 | 533 |  | 
 | 534 |     explicit TagNameKey(TagNameKey&& rval) | 
 | 535 |         : alloc(rval.alloc), name(rval.name.data(), rval.name.length()) { | 
 | 536 |         rval.alloc = nullptr; | 
 | 537 |     } | 
 | 538 |  | 
 | 539 |     explicit TagNameKey(const TagNameKey& rval) | 
 | 540 |         : alloc(rval.alloc ? new std::string(*rval.alloc) : nullptr), | 
 | 541 |           name(alloc ? alloc->data() : rval.name.data(), rval.name.length()) { | 
 | 542 |     } | 
 | 543 |  | 
 | 544 |     ~TagNameKey() { | 
 | 545 |         if (alloc) delete alloc; | 
 | 546 |     } | 
 | 547 |  | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 548 |     operator const std::string_view() const { | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 549 |         return name; | 
 | 550 |     } | 
 | 551 |  | 
 | 552 |     const char* data() const { | 
 | 553 |         return name.data(); | 
 | 554 |     } | 
 | 555 |     size_t length() const { | 
 | 556 |         return name.length(); | 
 | 557 |     } | 
 | 558 |  | 
 | 559 |     bool operator==(const TagNameKey& rval) const { | 
 | 560 |         if (length() != rval.length()) return false; | 
 | 561 |         if (length() == 0) return true; | 
 | 562 |         return fastcmp<strncmp>(data(), rval.data(), length()) == 0; | 
 | 563 |     } | 
 | 564 |     bool operator!=(const TagNameKey& rval) const { | 
 | 565 |         return !(*this == rval); | 
 | 566 |     } | 
 | 567 |  | 
 | 568 |     size_t getAllocLength() const { | 
 | 569 |         return alloc ? alloc->length() + 1 + sizeof(std::string) : 0; | 
 | 570 |     } | 
 | 571 | }; | 
 | 572 |  | 
 | 573 | // Hash for TagNameKey | 
 | 574 | template <> | 
 | 575 | struct std::hash<TagNameKey> | 
 | 576 |     : public std::unary_function<const TagNameKey&, size_t> { | 
 | 577 |     size_t operator()(const TagNameKey& __t) const noexcept { | 
 | 578 |         if (!__t.length()) return 0; | 
| Elliott Hughes | e805883 | 2017-11-30 16:31:35 -0800 | [diff] [blame] | 579 |         return std::hash<std::string_view>()(std::string_view(__t)); | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 580 |     } | 
 | 581 | }; | 
 | 582 |  | 
 | 583 | struct TagNameEntry : public EntryBase { | 
 | 584 |     pid_t tid; | 
 | 585 |     pid_t pid; | 
 | 586 |     uid_t uid; | 
 | 587 |     TagNameKey name; | 
 | 588 |  | 
 | 589 |     explicit TagNameEntry(const LogBufferElement* element) | 
 | 590 |         : EntryBase(element), | 
 | 591 |           tid(element->getTid()), | 
 | 592 |           pid(element->getPid()), | 
 | 593 |           uid(element->getUid()), | 
 | 594 |           name(element) { | 
 | 595 |     } | 
 | 596 |  | 
 | 597 |     const TagNameKey& getKey() const { | 
 | 598 |         return name; | 
 | 599 |     } | 
 | 600 |     const pid_t& getTid() const { | 
 | 601 |         return tid; | 
 | 602 |     } | 
 | 603 |     const pid_t& getPid() const { | 
 | 604 |         return pid; | 
 | 605 |     } | 
 | 606 |     const uid_t& getUid() const { | 
 | 607 |         return uid; | 
 | 608 |     } | 
 | 609 |     const char* getName() const { | 
 | 610 |         return name.data(); | 
 | 611 |     } | 
 | 612 |     size_t getNameAllocLength() const { | 
 | 613 |         return name.getAllocLength(); | 
 | 614 |     } | 
 | 615 |  | 
 | 616 |     inline void add(const LogBufferElement* element) { | 
 | 617 |         if (uid != element->getUid()) { | 
 | 618 |             uid = -1; | 
 | 619 |         } | 
 | 620 |         if (pid != element->getPid()) { | 
 | 621 |             pid = -1; | 
 | 622 |         } | 
 | 623 |         if (tid != element->getTid()) { | 
 | 624 |             tid = -1; | 
 | 625 |         } | 
 | 626 |         EntryBase::add(element); | 
 | 627 |     } | 
 | 628 |  | 
 | 629 |     std::string formatHeader(const std::string& name, log_id_t id) const; | 
 | 630 |     std::string format(const LogStatistics& stat, log_id_t id) const; | 
 | 631 | }; | 
 | 632 |  | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 633 | template <typename TEntry> | 
 | 634 | class LogFindWorst { | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 635 |     std::unique_ptr<const TEntry* []> sorted; | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 636 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 637 |    public: | 
 | 638 |     explicit LogFindWorst(std::unique_ptr<const TEntry* []>&& sorted) | 
 | 639 |         : sorted(std::move(sorted)) { | 
 | 640 |     } | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 641 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 642 |     void findWorst(int& worst, size_t& worst_sizes, size_t& second_worst_sizes, | 
 | 643 |                    size_t threshold) { | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 644 |         if (sorted.get() && sorted[0] && sorted[1]) { | 
 | 645 |             worst_sizes = sorted[0]->getSizes(); | 
 | 646 |             if ((worst_sizes > threshold) | 
 | 647 |                 // Allow time horizon to extend roughly tenfold, assume | 
 | 648 |                 // average entry length is 100 characters. | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 649 |                 && (worst_sizes > (10 * sorted[0]->getDropped()))) { | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 650 |                 worst = sorted[0]->getKey(); | 
 | 651 |                 second_worst_sizes = sorted[1]->getSizes(); | 
 | 652 |                 if (second_worst_sizes < threshold) { | 
 | 653 |                     second_worst_sizes = threshold; | 
 | 654 |                 } | 
 | 655 |             } | 
 | 656 |         } | 
 | 657 |     } | 
 | 658 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 659 |     void findWorst(int& worst, size_t worst_sizes, size_t& second_worst_sizes) { | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 660 |         if (sorted.get() && sorted[0] && sorted[1]) { | 
 | 661 |             worst = sorted[0]->getKey(); | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 662 |             second_worst_sizes = | 
 | 663 |                 worst_sizes - sorted[0]->getSizes() + sorted[1]->getSizes(); | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 664 |         } | 
 | 665 |     } | 
 | 666 | }; | 
 | 667 |  | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 668 | // Log Statistics | 
 | 669 | class LogStatistics { | 
| Mark Salyzyn | c723df8 | 2015-08-24 11:08:00 -0700 | [diff] [blame] | 670 |     friend UidEntry; | 
 | 671 |  | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 672 |     size_t mSizes[LOG_ID_MAX]; | 
 | 673 |     size_t mElements[LOG_ID_MAX]; | 
| Mark Salyzyn | 58b8be8 | 2015-09-30 07:40:09 -0700 | [diff] [blame] | 674 |     size_t mDroppedElements[LOG_ID_MAX]; | 
| Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 675 |     size_t mSizesTotal[LOG_ID_MAX]; | 
 | 676 |     size_t mElementsTotal[LOG_ID_MAX]; | 
| Mark Salyzyn | 03bb759 | 2017-04-14 09:46:57 -0700 | [diff] [blame] | 677 |     log_time mOldest[LOG_ID_MAX]; | 
 | 678 |     log_time mNewest[LOG_ID_MAX]; | 
 | 679 |     log_time mNewestDropped[LOG_ID_MAX]; | 
| Mark Salyzyn | 3296291 | 2016-09-12 10:29:17 -0700 | [diff] [blame] | 680 |     static size_t SizesTotal; | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 681 |     bool enable; | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 682 |  | 
| Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 683 |     // uid to size list | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 684 |     typedef LogHashtable<uid_t, UidEntry> uidTable_t; | 
| Mark Salyzyn | 97c1c2b | 2015-03-10 13:51:35 -0700 | [diff] [blame] | 685 |     uidTable_t uidTable[LOG_ID_MAX]; | 
| Mark Salyzyn | e457b74 | 2014-02-19 17:18:31 -0800 | [diff] [blame] | 686 |  | 
| Mark Salyzyn | bec3c3d | 2015-08-28 08:02:59 -0700 | [diff] [blame] | 687 |     // pid of system to size list | 
 | 688 |     typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t; | 
 | 689 |     pidSystemTable_t pidSystemTable[LOG_ID_MAX]; | 
 | 690 |  | 
| Mark Salyzyn | 720f6d1 | 2015-03-16 08:26:05 -0700 | [diff] [blame] | 691 |     // pid to uid list | 
 | 692 |     typedef LogHashtable<pid_t, PidEntry> pidTable_t; | 
 | 693 |     pidTable_t pidTable; | 
 | 694 |  | 
| Mark Salyzyn | 17ed679 | 2015-04-20 13:35:15 -0700 | [diff] [blame] | 695 |     // tid to uid list | 
 | 696 |     typedef LogHashtable<pid_t, TidEntry> tidTable_t; | 
 | 697 |     tidTable_t tidTable; | 
 | 698 |  | 
| Mark Salyzyn | 344bff4 | 2015-04-13 14:24:45 -0700 | [diff] [blame] | 699 |     // tag list | 
 | 700 |     typedef LogHashtable<uint32_t, TagEntry> tagTable_t; | 
 | 701 |     tagTable_t tagTable; | 
 | 702 |  | 
| Mark Salyzyn | 083b037 | 2015-12-04 10:59:45 -0800 | [diff] [blame] | 703 |     // security tag list | 
 | 704 |     tagTable_t securityTagTable; | 
 | 705 |  | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 706 |     // global tag list | 
 | 707 |     typedef LogHashtable<TagNameKey, TagNameEntry> tagNameTable_t; | 
 | 708 |     tagNameTable_t tagNameTable; | 
 | 709 |  | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 710 |     size_t sizeOf() const { | 
 | 711 |         size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() + | 
| Mark Salyzyn | b067229 | 2016-10-06 10:09:24 -0700 | [diff] [blame] | 712 |                       tagTable.sizeOf() + securityTagTable.sizeOf() + | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 713 |                       tagNameTable.sizeOf() + | 
| Mark Salyzyn | b067229 | 2016-10-06 10:09:24 -0700 | [diff] [blame] | 714 |                       (pidTable.size() * sizeof(pidTable_t::iterator)) + | 
 | 715 |                       (tagTable.size() * sizeof(tagTable_t::iterator)); | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 716 |         for (auto it : pidTable) { | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 717 |             const char* name = it.second.getName(); | 
 | 718 |             if (name) size += strlen(name) + 1; | 
 | 719 |         } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 720 |         for (auto it : tidTable) { | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 721 |             const char* name = it.second.getName(); | 
 | 722 |             if (name) size += strlen(name) + 1; | 
 | 723 |         } | 
| Mark Salyzyn | f99a7d6 | 2017-04-19 14:39:21 -0700 | [diff] [blame] | 724 |         for (auto it : tagNameTable) size += it.second.getNameAllocLength(); | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 725 |         log_id_for_each(id) { | 
 | 726 |             size += uidTable[id].sizeOf(); | 
| Mark Salyzyn | b067229 | 2016-10-06 10:09:24 -0700 | [diff] [blame] | 727 |             size += uidTable[id].size() * sizeof(uidTable_t::iterator); | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 728 |             size += pidSystemTable[id].sizeOf(); | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 729 |             size += | 
 | 730 |                 pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator); | 
| Mark Salyzyn | 6d981af | 2016-10-06 09:55:21 -0700 | [diff] [blame] | 731 |         } | 
 | 732 |         return size; | 
 | 733 |     } | 
 | 734 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 735 |    public: | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 736 |     LogStatistics(); | 
 | 737 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 738 |     void enableStatistics() { | 
 | 739 |         enable = true; | 
 | 740 |     } | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 741 |  | 
| Mark Salyzyn | 02dd2f4 | 2017-04-14 09:46:57 -0700 | [diff] [blame] | 742 |     void addTotal(LogBufferElement* entry); | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 743 |     void add(LogBufferElement* entry); | 
 | 744 |     void subtract(LogBufferElement* entry); | 
| Mark Salyzyn | ab0dcf6 | 2015-03-16 12:04:09 -0700 | [diff] [blame] | 745 |     // entry->setDropped(1) must follow this call | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 746 |     void drop(LogBufferElement* entry); | 
| Mark Salyzyn | aaad42f | 2015-09-30 07:40:09 -0700 | [diff] [blame] | 747 |     // Correct for coalescing two entries referencing dropped content | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 748 |     void erase(LogBufferElement* element) { | 
| Mark Salyzyn | 58b8be8 | 2015-09-30 07:40:09 -0700 | [diff] [blame] | 749 |         log_id_t log_id = element->getLogId(); | 
 | 750 |         --mElements[log_id]; | 
 | 751 |         --mDroppedElements[log_id]; | 
 | 752 |     } | 
| Mark Salyzyn | e457b74 | 2014-02-19 17:18:31 -0800 | [diff] [blame] | 753 |  | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 754 |     LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) { | 
 | 755 |         return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len)); | 
| Mark Salyzyn | 758058f | 2015-08-21 16:44:30 -0700 | [diff] [blame] | 756 |     } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 757 |     LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len, | 
 | 758 |                                     log_id id) { | 
| Mark Salyzyn | 6a06694 | 2016-07-14 15:34:30 -0700 | [diff] [blame] | 759 |         return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len)); | 
 | 760 |     } | 
 | 761 |     LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) { | 
 | 762 |         return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len)); | 
| Mark Salyzyn | bec3c3d | 2015-08-28 08:02:59 -0700 | [diff] [blame] | 763 |     } | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 764 |  | 
 | 765 |     // fast track current value by id only | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 766 |     size_t sizes(log_id_t id) const { | 
 | 767 |         return mSizes[id]; | 
 | 768 |     } | 
 | 769 |     size_t elements(log_id_t id) const { | 
 | 770 |         return mElements[id]; | 
 | 771 |     } | 
| Mark Salyzyn | 58b8be8 | 2015-09-30 07:40:09 -0700 | [diff] [blame] | 772 |     size_t realElements(log_id_t id) const { | 
 | 773 |         return mElements[id] - mDroppedElements[id]; | 
 | 774 |     } | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 775 |     size_t sizesTotal(log_id_t id) const { | 
 | 776 |         return mSizesTotal[id]; | 
 | 777 |     } | 
 | 778 |     size_t elementsTotal(log_id_t id) const { | 
 | 779 |         return mElementsTotal[id]; | 
 | 780 |     } | 
 | 781 |     static size_t sizesTotal() { | 
 | 782 |         return SizesTotal; | 
 | 783 |     } | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 784 |  | 
| Mark Salyzyn | ee3b838 | 2015-12-17 09:58:43 -0800 | [diff] [blame] | 785 |     std::string format(uid_t uid, pid_t pid, unsigned int logMask) const; | 
| Mark Salyzyn | 9a03863 | 2014-04-07 07:05:40 -0700 | [diff] [blame] | 786 |  | 
| Mark Salyzyn | ed777e9 | 2015-06-24 16:22:54 -0700 | [diff] [blame] | 787 |     // helper (must be locked directly or implicitly by mLogElementsLock) | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 788 |     const char* pidToName(pid_t pid) const; | 
| Mark Salyzyn | 4ba0387 | 2014-04-07 07:15:33 -0700 | [diff] [blame] | 789 |     uid_t pidToUid(pid_t pid); | 
| Mark Salyzyn | c4e4823 | 2017-05-04 13:54:46 -0700 | [diff] [blame] | 790 |     pid_t tidToPid(pid_t tid); | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 791 |     const char* uidToName(uid_t uid) const; | 
| Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 792 | }; | 
 | 793 |  | 
| Mark Salyzyn | 501c373 | 2017-03-10 14:31:54 -0800 | [diff] [blame] | 794 | #endif  // _LOGD_LOG_STATISTICS_H__ |