Loading logd/LogStatistics.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,10 @@ void LogStatistics::add(LogBufferElement* element) { tagTable.add(tag, element); } } if (!element->getDropped()) { tagNameTable.add(TagNameKey(element), element); } } void LogStatistics::subtract(LogBufferElement* element) { Loading Loading @@ -191,6 +195,10 @@ void LogStatistics::subtract(LogBufferElement* element) { tagTable.subtract(tag, element); } } if (!element->getDropped()) { tagNameTable.subtract(TagNameKey(element), element); } } // Atomically set an entry to drop Loading Loading @@ -225,6 +233,8 @@ void LogStatistics::drop(LogBufferElement* element) { tagTable.drop(tag, element); } } tagNameTable.subtract(TagNameKey(element), element); } // caller must own and free character string Loading Loading @@ -505,6 +515,62 @@ std::string TagEntry::format(const LogStatistics& /* stat */, return formatLine(name, size, pruned); } std::string TagNameEntry::formatHeader(const std::string& name, log_id_t /* id */) const { return formatLine(name, std::string("Size"), std::string("")) + formatLine(std::string(" TID/PID/UID LOG_TAG NAME"), std::string("BYTES"), std::string("")); } std::string TagNameEntry::format(const LogStatistics& /* stat */, log_id_t /* id */) const { std::string name; pid_t tid = getTid(); pid_t pid = getPid(); std::string pidstr; if (pid != (pid_t)-1) { pidstr = android::base::StringPrintf("%u", pid); if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr; } int len = 9 - pidstr.length(); if (len < 0) len = 0; if ((tid == (pid_t)-1) || (tid == pid)) { name = android::base::StringPrintf("%*s", len, ""); } else { name = android::base::StringPrintf("%*u", len, tid); } name += pidstr; uid_t uid = getUid(); if (uid != (uid_t)-1) { name += android::base::StringPrintf("/%u", uid); } std::string size = android::base::StringPrintf("%zu", getSizes()); const char* nameTmp = getName(); if (nameTmp) { size_t lenSpace = std::max(16 - name.length(), (size_t)1); size_t len = EntryBaseConstants::total_len - EntryBaseConstants::pruned_len - size.length() - name.length() - lenSpace - 2; size_t lenNameTmp = strlen(nameTmp); while ((len < lenNameTmp) && (lenSpace > 1)) { ++len; --lenSpace; } name += android::base::StringPrintf("%*s", (int)lenSpace, ""); if (len < lenNameTmp) { name += "..."; nameTmp += lenNameTmp - std::max(len - 3, (size_t)1); } name += nameTmp; } std::string pruned = ""; return formatLine(name, size, pruned); } static std::string formatMsec(uint64_t val) { static const unsigned subsecDigits = 3; static const uint64_t sec = MS_PER_SEC; Loading Loading @@ -740,6 +806,13 @@ std::string LogStatistics::format(uid_t uid, pid_t pid, securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY); } if (enable) { name = "Chattiest TAGs"; if (pid) name += android::base::StringPrintf(" for PID %d", pid); name += ":"; output += tagNameTable.format(*this, uid, pid, name); } return output; } Loading logd/LogStatistics.h +180 −23 Original line number Diff line number Diff line Loading @@ -18,10 +18,14 @@ #define _LOGD_LOG_STATISTICS_H__ #include <ctype.h> #include <inttypes.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <algorithm> // std::max #include <experimental/string_view> #include <memory> #include <string> // std::string #include <unordered_map> Loading @@ -30,6 +34,7 @@ #include <android/log.h> #include <log/log_time.h> #include <private/android_filesystem_config.h> #include <utils/FastStrcmp.h> #include "LogBufferElement.h" #include "LogUtils.h" Loading Loading @@ -77,7 +82,7 @@ class LogHashtable { std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid, size_t len) const { if (!len) { std::unique_ptr<const TEntry* []> sorted(NULL); std::unique_ptr<const TEntry* []> sorted(nullptr); return sorted; } Loading Loading @@ -112,7 +117,7 @@ class LogHashtable { return sorted; } inline iterator add(TKey key, LogBufferElement* element) { inline iterator add(const TKey& key, const LogBufferElement* element) { iterator it = map.find(key); if (it == map.end()) { it = map.insert(std::make_pair(key, TEntry(element))).first; Loading @@ -132,14 +137,21 @@ class LogHashtable { return it; } void subtract(TKey key, LogBufferElement* element) { void subtract(TKey&& key, const LogBufferElement* element) { iterator it = map.find(std::move(key)); if ((it != map.end()) && it->second.subtract(element)) { map.erase(it); } } void subtract(const TKey& key, const LogBufferElement* element) { iterator it = map.find(key); if ((it != map.end()) && it->second.subtract(element)) { map.erase(it); } } inline void drop(TKey key, LogBufferElement* element) { inline void drop(TKey key, const LogBufferElement* element) { iterator it = map.find(key); if (it != map.end()) { it->second.drop(element); Loading Loading @@ -199,17 +211,18 @@ struct EntryBase { EntryBase() : size(0) { } explicit EntryBase(LogBufferElement* element) : size(element->getMsgLen()) { explicit EntryBase(const LogBufferElement* element) : size(element->getMsgLen()) { } size_t getSizes() const { return size; } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { size += element->getMsgLen(); } inline bool subtract(LogBufferElement* element) { inline bool subtract(const LogBufferElement* element) { size -= element->getMsgLen(); return !size; } Loading Loading @@ -240,7 +253,7 @@ struct EntryBaseDropped : public EntryBase { EntryBaseDropped() : dropped(0) { } explicit EntryBaseDropped(LogBufferElement* element) explicit EntryBaseDropped(const LogBufferElement* element) : EntryBase(element), dropped(element->getDropped()) { } Loading @@ -248,15 +261,15 @@ struct EntryBaseDropped : public EntryBase { return dropped; } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { dropped += element->getDropped(); EntryBase::add(element); } inline bool subtract(LogBufferElement* element) { inline bool subtract(const LogBufferElement* element) { dropped -= element->getDropped(); return EntryBase::subtract(element) && !dropped; } inline void drop(LogBufferElement* element) { inline void drop(const LogBufferElement* element) { dropped += 1; EntryBase::subtract(element); } Loading @@ -266,7 +279,7 @@ struct UidEntry : public EntryBaseDropped { const uid_t uid; pid_t pid; explicit UidEntry(LogBufferElement* element) explicit UidEntry(const LogBufferElement* element) : EntryBaseDropped(element), uid(element->getUid()), pid(element->getPid()) { Loading @@ -282,7 +295,7 @@ struct UidEntry : public EntryBaseDropped { return pid; } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { if (pid != element->getPid()) { pid = -1; } Loading @@ -308,7 +321,7 @@ struct PidEntry : public EntryBaseDropped { uid(android::pidToUid(pid)), name(android::pidToName(pid)) { } explicit PidEntry(LogBufferElement* element) explicit PidEntry(const LogBufferElement* element) : EntryBaseDropped(element), pid(element->getPid()), uid(element->getUid()), Loading @@ -318,7 +331,7 @@ struct PidEntry : public EntryBaseDropped { : EntryBaseDropped(element), pid(element.pid), uid(element.uid), name(element.name ? strdup(element.name) : NULL) { name(element.name ? strdup(element.name) : nullptr) { } ~PidEntry() { free(name); Loading @@ -340,14 +353,14 @@ struct PidEntry : public EntryBaseDropped { inline void add(pid_t newPid) { if (name && !fastcmp<strncmp>(name, "zygote", 6)) { free(name); name = NULL; name = nullptr; } if (!name) { name = android::pidToName(newPid); } } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { uid_t incomingUid = element->getUid(); if (getUid() != incomingUid) { uid = incomingUid; Loading Loading @@ -376,7 +389,7 @@ struct TidEntry : public EntryBaseDropped { uid(android::pidToUid(tid)), name(android::tidToName(tid)) { } explicit TidEntry(LogBufferElement* element) explicit TidEntry(const LogBufferElement* element) : EntryBaseDropped(element), tid(element->getTid()), pid(element->getPid()), Loading @@ -388,7 +401,7 @@ struct TidEntry : public EntryBaseDropped { tid(element.tid), pid(element.pid), uid(element.uid), name(element.name ? strdup(element.name) : NULL) { name(element.name ? strdup(element.name) : nullptr) { } ~TidEntry() { free(name); Loading @@ -413,14 +426,14 @@ struct TidEntry : public EntryBaseDropped { inline void add(pid_t incomingTid) { if (name && !fastcmp<strncmp>(name, "zygote", 6)) { free(name); name = NULL; name = nullptr; } if (!name) { name = android::tidToName(incomingTid); } } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { uid_t incomingUid = element->getUid(); pid_t incomingPid = element->getPid(); if ((getUid() != incomingUid) || (getPid() != incomingPid)) { Loading @@ -443,7 +456,7 @@ struct TagEntry : public EntryBaseDropped { pid_t pid; uid_t uid; explicit TagEntry(LogBufferElement* element) explicit TagEntry(const LogBufferElement* element) : EntryBaseDropped(element), tag(element->getTag()), pid(element->getPid()), Loading @@ -463,7 +476,7 @@ struct TagEntry : public EntryBaseDropped { return android::tagToName(tag); } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { if (uid != element->getUid()) { uid = -1; } Loading @@ -477,6 +490,144 @@ struct TagEntry : public EntryBaseDropped { std::string format(const LogStatistics& stat, log_id_t id) const; }; struct TagNameKey { std::string* alloc; std::experimental::string_view name; // Saves space if const char* explicit TagNameKey(const LogBufferElement* element) : alloc(nullptr), name("", strlen("")) { if (element->isBinary()) { uint32_t tag = element->getTag(); if (tag) { const char* cp = android::tagToName(tag); if (cp) { name = std::experimental::string_view(cp, strlen(cp)); return; } } alloc = new std::string( android::base::StringPrintf("[%" PRIu32 "]", tag)); if (!alloc) return; name = std::experimental::string_view(alloc->c_str(), alloc->size()); return; } const char* msg = element->getMsg(); if (!msg) { name = std::experimental::string_view("chatty", strlen("chatty")); return; } ++msg; unsigned short len = element->getMsgLen(); len = (len <= 1) ? 0 : strnlen(msg, len - 1); if (!len) { name = std::experimental::string_view("<NULL>", strlen("<NULL>")); return; } alloc = new std::string(msg, len); if (!alloc) return; name = std::experimental::string_view(alloc->c_str(), alloc->size()); } explicit TagNameKey(TagNameKey&& rval) : alloc(rval.alloc), name(rval.name.data(), rval.name.length()) { rval.alloc = nullptr; } explicit TagNameKey(const TagNameKey& rval) : alloc(rval.alloc ? new std::string(*rval.alloc) : nullptr), name(alloc ? alloc->data() : rval.name.data(), rval.name.length()) { } ~TagNameKey() { if (alloc) delete alloc; } operator const std::experimental::string_view() const { return name; } const char* data() const { return name.data(); } size_t length() const { return name.length(); } bool operator==(const TagNameKey& rval) const { if (length() != rval.length()) return false; if (length() == 0) return true; return fastcmp<strncmp>(data(), rval.data(), length()) == 0; } bool operator!=(const TagNameKey& rval) const { return !(*this == rval); } size_t getAllocLength() const { return alloc ? alloc->length() + 1 + sizeof(std::string) : 0; } }; // Hash for TagNameKey template <> struct std::hash<TagNameKey> : public std::unary_function<const TagNameKey&, size_t> { size_t operator()(const TagNameKey& __t) const noexcept { if (!__t.length()) return 0; return std::hash<std::experimental::string_view>()( std::experimental::string_view(__t)); } }; struct TagNameEntry : public EntryBase { pid_t tid; pid_t pid; uid_t uid; TagNameKey name; explicit TagNameEntry(const LogBufferElement* element) : EntryBase(element), tid(element->getTid()), pid(element->getPid()), uid(element->getUid()), name(element) { } const TagNameKey& getKey() const { return name; } const pid_t& getTid() const { return tid; } const pid_t& getPid() const { return pid; } const uid_t& getUid() const { return uid; } const char* getName() const { return name.data(); } size_t getNameAllocLength() const { return name.getAllocLength(); } inline void add(const LogBufferElement* element) { if (uid != element->getUid()) { uid = -1; } if (pid != element->getPid()) { pid = -1; } if (tid != element->getTid()) { tid = -1; } EntryBase::add(element); } std::string formatHeader(const std::string& name, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const; }; template <typename TEntry> class LogFindWorst { std::unique_ptr<const TEntry* []> sorted; Loading Loading @@ -550,9 +701,14 @@ class LogStatistics { // security tag list tagTable_t securityTagTable; // global tag list typedef LogHashtable<TagNameKey, TagNameEntry> tagNameTable_t; tagNameTable_t tagNameTable; size_t sizeOf() const { size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() + tagTable.sizeOf() + securityTagTable.sizeOf() + tagNameTable.sizeOf() + (pidTable.size() * sizeof(pidTable_t::iterator)) + (tagTable.size() * sizeof(tagTable_t::iterator)); for (auto it : pidTable) { Loading @@ -563,6 +719,7 @@ class LogStatistics { const char* name = it.second.getName(); if (name) size += strlen(name) + 1; } for (auto it : tagNameTable) size += it.second.getNameAllocLength(); log_id_for_each(id) { size += uidTable[id].sizeOf(); size += uidTable[id].size() * sizeof(uidTable_t::iterator); Loading Loading
logd/LogStatistics.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,10 @@ void LogStatistics::add(LogBufferElement* element) { tagTable.add(tag, element); } } if (!element->getDropped()) { tagNameTable.add(TagNameKey(element), element); } } void LogStatistics::subtract(LogBufferElement* element) { Loading Loading @@ -191,6 +195,10 @@ void LogStatistics::subtract(LogBufferElement* element) { tagTable.subtract(tag, element); } } if (!element->getDropped()) { tagNameTable.subtract(TagNameKey(element), element); } } // Atomically set an entry to drop Loading Loading @@ -225,6 +233,8 @@ void LogStatistics::drop(LogBufferElement* element) { tagTable.drop(tag, element); } } tagNameTable.subtract(TagNameKey(element), element); } // caller must own and free character string Loading Loading @@ -505,6 +515,62 @@ std::string TagEntry::format(const LogStatistics& /* stat */, return formatLine(name, size, pruned); } std::string TagNameEntry::formatHeader(const std::string& name, log_id_t /* id */) const { return formatLine(name, std::string("Size"), std::string("")) + formatLine(std::string(" TID/PID/UID LOG_TAG NAME"), std::string("BYTES"), std::string("")); } std::string TagNameEntry::format(const LogStatistics& /* stat */, log_id_t /* id */) const { std::string name; pid_t tid = getTid(); pid_t pid = getPid(); std::string pidstr; if (pid != (pid_t)-1) { pidstr = android::base::StringPrintf("%u", pid); if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr; } int len = 9 - pidstr.length(); if (len < 0) len = 0; if ((tid == (pid_t)-1) || (tid == pid)) { name = android::base::StringPrintf("%*s", len, ""); } else { name = android::base::StringPrintf("%*u", len, tid); } name += pidstr; uid_t uid = getUid(); if (uid != (uid_t)-1) { name += android::base::StringPrintf("/%u", uid); } std::string size = android::base::StringPrintf("%zu", getSizes()); const char* nameTmp = getName(); if (nameTmp) { size_t lenSpace = std::max(16 - name.length(), (size_t)1); size_t len = EntryBaseConstants::total_len - EntryBaseConstants::pruned_len - size.length() - name.length() - lenSpace - 2; size_t lenNameTmp = strlen(nameTmp); while ((len < lenNameTmp) && (lenSpace > 1)) { ++len; --lenSpace; } name += android::base::StringPrintf("%*s", (int)lenSpace, ""); if (len < lenNameTmp) { name += "..."; nameTmp += lenNameTmp - std::max(len - 3, (size_t)1); } name += nameTmp; } std::string pruned = ""; return formatLine(name, size, pruned); } static std::string formatMsec(uint64_t val) { static const unsigned subsecDigits = 3; static const uint64_t sec = MS_PER_SEC; Loading Loading @@ -740,6 +806,13 @@ std::string LogStatistics::format(uid_t uid, pid_t pid, securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY); } if (enable) { name = "Chattiest TAGs"; if (pid) name += android::base::StringPrintf(" for PID %d", pid); name += ":"; output += tagNameTable.format(*this, uid, pid, name); } return output; } Loading
logd/LogStatistics.h +180 −23 Original line number Diff line number Diff line Loading @@ -18,10 +18,14 @@ #define _LOGD_LOG_STATISTICS_H__ #include <ctype.h> #include <inttypes.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <algorithm> // std::max #include <experimental/string_view> #include <memory> #include <string> // std::string #include <unordered_map> Loading @@ -30,6 +34,7 @@ #include <android/log.h> #include <log/log_time.h> #include <private/android_filesystem_config.h> #include <utils/FastStrcmp.h> #include "LogBufferElement.h" #include "LogUtils.h" Loading Loading @@ -77,7 +82,7 @@ class LogHashtable { std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid, size_t len) const { if (!len) { std::unique_ptr<const TEntry* []> sorted(NULL); std::unique_ptr<const TEntry* []> sorted(nullptr); return sorted; } Loading Loading @@ -112,7 +117,7 @@ class LogHashtable { return sorted; } inline iterator add(TKey key, LogBufferElement* element) { inline iterator add(const TKey& key, const LogBufferElement* element) { iterator it = map.find(key); if (it == map.end()) { it = map.insert(std::make_pair(key, TEntry(element))).first; Loading @@ -132,14 +137,21 @@ class LogHashtable { return it; } void subtract(TKey key, LogBufferElement* element) { void subtract(TKey&& key, const LogBufferElement* element) { iterator it = map.find(std::move(key)); if ((it != map.end()) && it->second.subtract(element)) { map.erase(it); } } void subtract(const TKey& key, const LogBufferElement* element) { iterator it = map.find(key); if ((it != map.end()) && it->second.subtract(element)) { map.erase(it); } } inline void drop(TKey key, LogBufferElement* element) { inline void drop(TKey key, const LogBufferElement* element) { iterator it = map.find(key); if (it != map.end()) { it->second.drop(element); Loading Loading @@ -199,17 +211,18 @@ struct EntryBase { EntryBase() : size(0) { } explicit EntryBase(LogBufferElement* element) : size(element->getMsgLen()) { explicit EntryBase(const LogBufferElement* element) : size(element->getMsgLen()) { } size_t getSizes() const { return size; } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { size += element->getMsgLen(); } inline bool subtract(LogBufferElement* element) { inline bool subtract(const LogBufferElement* element) { size -= element->getMsgLen(); return !size; } Loading Loading @@ -240,7 +253,7 @@ struct EntryBaseDropped : public EntryBase { EntryBaseDropped() : dropped(0) { } explicit EntryBaseDropped(LogBufferElement* element) explicit EntryBaseDropped(const LogBufferElement* element) : EntryBase(element), dropped(element->getDropped()) { } Loading @@ -248,15 +261,15 @@ struct EntryBaseDropped : public EntryBase { return dropped; } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { dropped += element->getDropped(); EntryBase::add(element); } inline bool subtract(LogBufferElement* element) { inline bool subtract(const LogBufferElement* element) { dropped -= element->getDropped(); return EntryBase::subtract(element) && !dropped; } inline void drop(LogBufferElement* element) { inline void drop(const LogBufferElement* element) { dropped += 1; EntryBase::subtract(element); } Loading @@ -266,7 +279,7 @@ struct UidEntry : public EntryBaseDropped { const uid_t uid; pid_t pid; explicit UidEntry(LogBufferElement* element) explicit UidEntry(const LogBufferElement* element) : EntryBaseDropped(element), uid(element->getUid()), pid(element->getPid()) { Loading @@ -282,7 +295,7 @@ struct UidEntry : public EntryBaseDropped { return pid; } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { if (pid != element->getPid()) { pid = -1; } Loading @@ -308,7 +321,7 @@ struct PidEntry : public EntryBaseDropped { uid(android::pidToUid(pid)), name(android::pidToName(pid)) { } explicit PidEntry(LogBufferElement* element) explicit PidEntry(const LogBufferElement* element) : EntryBaseDropped(element), pid(element->getPid()), uid(element->getUid()), Loading @@ -318,7 +331,7 @@ struct PidEntry : public EntryBaseDropped { : EntryBaseDropped(element), pid(element.pid), uid(element.uid), name(element.name ? strdup(element.name) : NULL) { name(element.name ? strdup(element.name) : nullptr) { } ~PidEntry() { free(name); Loading @@ -340,14 +353,14 @@ struct PidEntry : public EntryBaseDropped { inline void add(pid_t newPid) { if (name && !fastcmp<strncmp>(name, "zygote", 6)) { free(name); name = NULL; name = nullptr; } if (!name) { name = android::pidToName(newPid); } } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { uid_t incomingUid = element->getUid(); if (getUid() != incomingUid) { uid = incomingUid; Loading Loading @@ -376,7 +389,7 @@ struct TidEntry : public EntryBaseDropped { uid(android::pidToUid(tid)), name(android::tidToName(tid)) { } explicit TidEntry(LogBufferElement* element) explicit TidEntry(const LogBufferElement* element) : EntryBaseDropped(element), tid(element->getTid()), pid(element->getPid()), Loading @@ -388,7 +401,7 @@ struct TidEntry : public EntryBaseDropped { tid(element.tid), pid(element.pid), uid(element.uid), name(element.name ? strdup(element.name) : NULL) { name(element.name ? strdup(element.name) : nullptr) { } ~TidEntry() { free(name); Loading @@ -413,14 +426,14 @@ struct TidEntry : public EntryBaseDropped { inline void add(pid_t incomingTid) { if (name && !fastcmp<strncmp>(name, "zygote", 6)) { free(name); name = NULL; name = nullptr; } if (!name) { name = android::tidToName(incomingTid); } } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { uid_t incomingUid = element->getUid(); pid_t incomingPid = element->getPid(); if ((getUid() != incomingUid) || (getPid() != incomingPid)) { Loading @@ -443,7 +456,7 @@ struct TagEntry : public EntryBaseDropped { pid_t pid; uid_t uid; explicit TagEntry(LogBufferElement* element) explicit TagEntry(const LogBufferElement* element) : EntryBaseDropped(element), tag(element->getTag()), pid(element->getPid()), Loading @@ -463,7 +476,7 @@ struct TagEntry : public EntryBaseDropped { return android::tagToName(tag); } inline void add(LogBufferElement* element) { inline void add(const LogBufferElement* element) { if (uid != element->getUid()) { uid = -1; } Loading @@ -477,6 +490,144 @@ struct TagEntry : public EntryBaseDropped { std::string format(const LogStatistics& stat, log_id_t id) const; }; struct TagNameKey { std::string* alloc; std::experimental::string_view name; // Saves space if const char* explicit TagNameKey(const LogBufferElement* element) : alloc(nullptr), name("", strlen("")) { if (element->isBinary()) { uint32_t tag = element->getTag(); if (tag) { const char* cp = android::tagToName(tag); if (cp) { name = std::experimental::string_view(cp, strlen(cp)); return; } } alloc = new std::string( android::base::StringPrintf("[%" PRIu32 "]", tag)); if (!alloc) return; name = std::experimental::string_view(alloc->c_str(), alloc->size()); return; } const char* msg = element->getMsg(); if (!msg) { name = std::experimental::string_view("chatty", strlen("chatty")); return; } ++msg; unsigned short len = element->getMsgLen(); len = (len <= 1) ? 0 : strnlen(msg, len - 1); if (!len) { name = std::experimental::string_view("<NULL>", strlen("<NULL>")); return; } alloc = new std::string(msg, len); if (!alloc) return; name = std::experimental::string_view(alloc->c_str(), alloc->size()); } explicit TagNameKey(TagNameKey&& rval) : alloc(rval.alloc), name(rval.name.data(), rval.name.length()) { rval.alloc = nullptr; } explicit TagNameKey(const TagNameKey& rval) : alloc(rval.alloc ? new std::string(*rval.alloc) : nullptr), name(alloc ? alloc->data() : rval.name.data(), rval.name.length()) { } ~TagNameKey() { if (alloc) delete alloc; } operator const std::experimental::string_view() const { return name; } const char* data() const { return name.data(); } size_t length() const { return name.length(); } bool operator==(const TagNameKey& rval) const { if (length() != rval.length()) return false; if (length() == 0) return true; return fastcmp<strncmp>(data(), rval.data(), length()) == 0; } bool operator!=(const TagNameKey& rval) const { return !(*this == rval); } size_t getAllocLength() const { return alloc ? alloc->length() + 1 + sizeof(std::string) : 0; } }; // Hash for TagNameKey template <> struct std::hash<TagNameKey> : public std::unary_function<const TagNameKey&, size_t> { size_t operator()(const TagNameKey& __t) const noexcept { if (!__t.length()) return 0; return std::hash<std::experimental::string_view>()( std::experimental::string_view(__t)); } }; struct TagNameEntry : public EntryBase { pid_t tid; pid_t pid; uid_t uid; TagNameKey name; explicit TagNameEntry(const LogBufferElement* element) : EntryBase(element), tid(element->getTid()), pid(element->getPid()), uid(element->getUid()), name(element) { } const TagNameKey& getKey() const { return name; } const pid_t& getTid() const { return tid; } const pid_t& getPid() const { return pid; } const uid_t& getUid() const { return uid; } const char* getName() const { return name.data(); } size_t getNameAllocLength() const { return name.getAllocLength(); } inline void add(const LogBufferElement* element) { if (uid != element->getUid()) { uid = -1; } if (pid != element->getPid()) { pid = -1; } if (tid != element->getTid()) { tid = -1; } EntryBase::add(element); } std::string formatHeader(const std::string& name, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const; }; template <typename TEntry> class LogFindWorst { std::unique_ptr<const TEntry* []> sorted; Loading Loading @@ -550,9 +701,14 @@ class LogStatistics { // security tag list tagTable_t securityTagTable; // global tag list typedef LogHashtable<TagNameKey, TagNameEntry> tagNameTable_t; tagNameTable_t tagNameTable; size_t sizeOf() const { size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() + tagTable.sizeOf() + securityTagTable.sizeOf() + tagNameTable.sizeOf() + (pidTable.size() * sizeof(pidTable_t::iterator)) + (tagTable.size() * sizeof(tagTable_t::iterator)); for (auto it : pidTable) { Loading @@ -563,6 +719,7 @@ class LogStatistics { const char* name = it.second.getName(); if (name) size += strlen(name) + 1; } for (auto it : tagNameTable) size += it.second.getNameAllocLength(); log_id_for_each(id) { size += uidTable[id].sizeOf(); size += uidTable[id].size() * sizeof(uidTable_t::iterator); Loading