Merge "logd: format LogBufferElement and LogStatistics correctly"

This commit is contained in:
Tom Cherry 2020-06-02 20:07:52 +00:00 committed by Gerrit Code Review
commit 4ab0bc414d
7 changed files with 479 additions and 594 deletions

View file

@ -48,38 +48,33 @@ ChattyLogBuffer::~ChattyLogBuffer() {}
enum match_type { DIFFERENT, SAME, SAME_LIBLOG }; enum match_type { DIFFERENT, SAME, SAME_LIBLOG };
static enum match_type Identical(LogBufferElement* elem, LogBufferElement* last) { static enum match_type Identical(const LogBufferElement& elem, const LogBufferElement& last) {
// is it mostly identical? ssize_t lenl = elem.msg_len();
// if (!elem) return DIFFERENT;
ssize_t lenl = elem->getMsgLen();
if (lenl <= 0) return DIFFERENT; // value if this represents a chatty elem if (lenl <= 0) return DIFFERENT; // value if this represents a chatty elem
// if (!last) return DIFFERENT; ssize_t lenr = last.msg_len();
ssize_t lenr = last->getMsgLen();
if (lenr <= 0) return DIFFERENT; // value if this represents a chatty elem if (lenr <= 0) return DIFFERENT; // value if this represents a chatty elem
// if (elem->getLogId() != last->getLogId()) return DIFFERENT; if (elem.uid() != last.uid()) return DIFFERENT;
if (elem->getUid() != last->getUid()) return DIFFERENT; if (elem.pid() != last.pid()) return DIFFERENT;
if (elem->getPid() != last->getPid()) return DIFFERENT; if (elem.tid() != last.tid()) return DIFFERENT;
if (elem->getTid() != last->getTid()) return DIFFERENT;
// last is more than a minute old, stop squashing identical messages // last is more than a minute old, stop squashing identical messages
if (elem->getRealTime().nsec() > (last->getRealTime().nsec() + 60 * NS_PER_SEC)) if (elem.realtime().nsec() > (last.realtime().nsec() + 60 * NS_PER_SEC)) return DIFFERENT;
return DIFFERENT;
// Identical message // Identical message
const char* msgl = elem->getMsg(); const char* msgl = elem.msg();
const char* msgr = last->getMsg(); const char* msgr = last.msg();
if (lenl == lenr) { if (lenl == lenr) {
if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME; if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME;
// liblog tagged messages (content gets summed) // liblog tagged messages (content gets summed)
if (elem->getLogId() == LOG_ID_EVENTS && lenl == sizeof(android_log_event_int_t) && if (elem.log_id() == LOG_ID_EVENTS && lenl == sizeof(android_log_event_int_t) &&
!fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_int_t) - sizeof(int32_t)) && !fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_int_t) - sizeof(int32_t)) &&
elem->getTag() == LIBLOG_LOG_TAG) { elem.GetTag() == LIBLOG_LOG_TAG) {
return SAME_LIBLOG; return SAME_LIBLOG;
} }
} }
// audit message (except sequence number) identical? // audit message (except sequence number) identical?
if (last->isBinary() && lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) && if (last.IsBinary() && lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) &&
lenr > static_cast<ssize_t>(sizeof(android_log_event_string_t))) { lenr > static_cast<ssize_t>(sizeof(android_log_event_string_t))) {
if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) - sizeof(int32_t))) { if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) - sizeof(int32_t))) {
return DIFFERENT; return DIFFERENT;
@ -105,11 +100,11 @@ static enum match_type Identical(LogBufferElement* elem, LogBufferElement* last)
void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) { void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
// b/137093665: don't coalesce security messages. // b/137093665: don't coalesce security messages.
if (elem.getLogId() == LOG_ID_SECURITY) { if (elem.log_id() == LOG_ID_SECURITY) {
SimpleLogBuffer::LogInternal(std::move(elem)); SimpleLogBuffer::LogInternal(std::move(elem));
return; return;
} }
int log_id = elem.getLogId(); int log_id = elem.log_id();
// Initialize last_logged_elements_ to a copy of elem if logging the first element for a log_id. // Initialize last_logged_elements_ to a copy of elem if logging the first element for a log_id.
if (!last_logged_elements_[log_id]) { if (!last_logged_elements_[log_id]) {
@ -119,12 +114,12 @@ void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
} }
LogBufferElement& current_last = *last_logged_elements_[log_id]; LogBufferElement& current_last = *last_logged_elements_[log_id];
enum match_type match = Identical(&elem, &current_last); enum match_type match = Identical(elem, current_last);
if (match == DIFFERENT) { if (match == DIFFERENT) {
if (duplicate_elements_[log_id]) { if (duplicate_elements_[log_id]) {
// If we previously had 3+ identical messages, log the chatty message. // If we previously had 3+ identical messages, log the chatty message.
if (duplicate_elements_[log_id]->getDropped() > 0) { if (duplicate_elements_[log_id]->dropped_count() > 0) {
SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id])); SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id]));
} }
duplicate_elements_[log_id].reset(); duplicate_elements_[log_id].reset();
@ -146,10 +141,10 @@ void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
// 3+ identical LIBLOG event messages: coalesce them into last_logged_elements_. // 3+ identical LIBLOG event messages: coalesce them into last_logged_elements_.
if (match == SAME_LIBLOG) { if (match == SAME_LIBLOG) {
const android_log_event_int_t* current_last_event = const android_log_event_int_t* current_last_event =
reinterpret_cast<const android_log_event_int_t*>(current_last.getMsg()); reinterpret_cast<const android_log_event_int_t*>(current_last.msg());
int64_t current_last_count = current_last_event->payload.data; int64_t current_last_count = current_last_event->payload.data;
android_log_event_int_t* elem_event = android_log_event_int_t* elem_event =
reinterpret_cast<android_log_event_int_t*>(const_cast<char*>(elem.getMsg())); reinterpret_cast<android_log_event_int_t*>(const_cast<char*>(elem.msg()));
int64_t elem_count = elem_event->payload.data; int64_t elem_count = elem_event->payload.data;
int64_t total = current_last_count + elem_count; int64_t total = current_last_count + elem_count;
@ -158,22 +153,22 @@ void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
last_logged_elements_[log_id].emplace(std::move(elem)); last_logged_elements_[log_id].emplace(std::move(elem));
return; return;
} }
stats()->AddTotal(current_last.getLogId(), current_last.getMsgLen()); stats()->AddTotal(current_last.log_id(), current_last.msg_len());
elem_event->payload.data = total; elem_event->payload.data = total;
last_logged_elements_[log_id].emplace(std::move(elem)); last_logged_elements_[log_id].emplace(std::move(elem));
return; return;
} }
// 3+ identical messages (not LIBLOG) messages: increase the drop count. // 3+ identical messages (not LIBLOG) messages: increase the drop count.
uint16_t dropped_count = duplicate_elements_[log_id]->getDropped(); uint16_t dropped_count = duplicate_elements_[log_id]->dropped_count();
if (dropped_count == std::numeric_limits<uint16_t>::max()) { if (dropped_count == std::numeric_limits<uint16_t>::max()) {
SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id])); SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id]));
dropped_count = 0; dropped_count = 0;
} }
// We're dropping the current_last log so add its stats to the total. // We're dropping the current_last log so add its stats to the total.
stats()->AddTotal(current_last.getLogId(), current_last.getMsgLen()); stats()->AddTotal(current_last.log_id(), current_last.msg_len());
// Use current_last for tracking the dropped count to always use the latest timestamp. // Use current_last for tracking the dropped count to always use the latest timestamp.
current_last.setDropped(dropped_count + 1); current_last.SetDropped(dropped_count + 1);
duplicate_elements_[log_id].emplace(std::move(current_last)); duplicate_elements_[log_id].emplace(std::move(current_last));
last_logged_elements_[log_id].emplace(std::move(elem)); last_logged_elements_[log_id].emplace(std::move(elem));
} }
@ -181,14 +176,13 @@ void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementCollection::iterator it, LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementCollection::iterator it,
bool coalesce) { bool coalesce) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
log_id_t id = element.getLogId(); log_id_t id = element.log_id();
// Remove iterator references in the various lists that will become stale // Remove iterator references in the various lists that will become stale
// after the element is erased from the main logging list. // after the element is erased from the main logging list.
{ // start of scope for found iterator { // start of scope for found iterator
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.getTag() int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.GetTag() : element.uid();
: element.getUid();
LogBufferIteratorMap::iterator found = mLastWorst[id].find(key); LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
if ((found != mLastWorst[id].end()) && (it == found->second)) { if ((found != mLastWorst[id].end()) && (it == found->second)) {
mLastWorst[id].erase(found); mLastWorst[id].erase(found);
@ -196,10 +190,10 @@ LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementColl
} }
{ // start of scope for pid found iterator { // start of scope for pid found iterator
// element->getUid() may not be AID_SYSTEM for next-best-watermark. // element->uid() may not be AID_SYSTEM for next-best-watermark.
// will not assume id != LOG_ID_EVENTS or LOG_ID_SECURITY for KISS and // will not assume id != LOG_ID_EVENTS or LOG_ID_SECURITY for KISS and
// long term code stability, find() check should be fast for those ids. // long term code stability, find() check should be fast for those ids.
LogBufferPidIteratorMap::iterator found = mLastWorstPidOfSystem[id].find(element.getPid()); LogBufferPidIteratorMap::iterator found = mLastWorstPidOfSystem[id].find(element.pid());
if (found != mLastWorstPidOfSystem[id].end() && it == found->second) { if (found != mLastWorstPidOfSystem[id].end() && it == found->second) {
mLastWorstPidOfSystem[id].erase(found); mLastWorstPidOfSystem[id].erase(found);
} }
@ -207,14 +201,13 @@ LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementColl
#ifdef DEBUG_CHECK_FOR_STALE_ENTRIES #ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
LogBufferElementCollection::iterator bad = it; LogBufferElementCollection::iterator bad = it;
int key = int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element->GetTag() : element->uid();
(id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element->getTag() : element->getUid();
#endif #endif
if (coalesce) { if (coalesce) {
stats()->Erase(&element); stats()->Erase(element);
} else { } else {
stats()->Subtract(&element); stats()->Subtract(element);
} }
it = SimpleLogBuffer::Erase(it); it = SimpleLogBuffer::Erase(it);
@ -245,15 +238,15 @@ class LogBufferElementLast {
public: public:
bool coalesce(LogBufferElement* element, uint16_t dropped) { bool coalesce(LogBufferElement* element, uint16_t dropped) {
uint64_t key = LogBufferElementKey(element->getUid(), element->getPid(), element->getTid()); uint64_t key = LogBufferElementKey(element->uid(), element->pid(), element->tid());
LogBufferElementMap::iterator it = map.find(key); LogBufferElementMap::iterator it = map.find(key);
if (it != map.end()) { if (it != map.end()) {
LogBufferElement* found = it->second; LogBufferElement* found = it->second;
uint16_t moreDropped = found->getDropped(); uint16_t moreDropped = found->dropped_count();
if ((dropped + moreDropped) > USHRT_MAX) { if ((dropped + moreDropped) > USHRT_MAX) {
map.erase(it); map.erase(it);
} else { } else {
found->setDropped(dropped + moreDropped); found->SetDropped(dropped + moreDropped);
return true; return true;
} }
} }
@ -261,18 +254,18 @@ class LogBufferElementLast {
} }
void add(LogBufferElement* element) { void add(LogBufferElement* element) {
uint64_t key = LogBufferElementKey(element->getUid(), element->getPid(), element->getTid()); uint64_t key = LogBufferElementKey(element->uid(), element->pid(), element->tid());
map[key] = element; map[key] = element;
} }
void clear() { map.clear(); } void clear() { map.clear(); }
void clear(LogBufferElement* element) { void clear(LogBufferElement* element) {
uint64_t current = element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC); uint64_t current = element->realtime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) { for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
LogBufferElement* mapElement = it->second; LogBufferElement* mapElement = it->second;
if (mapElement->getDropped() >= EXPIRE_THRESHOLD && if (mapElement->dropped_count() >= EXPIRE_THRESHOLD &&
current > mapElement->getRealTime().nsec()) { current > mapElement->realtime().nsec()) {
it = map.erase(it); it = map.erase(it);
} else { } else {
++it; ++it;
@ -359,12 +352,12 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
while (it != logs().end()) { while (it != logs().end()) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
if (element.getLogId() != id || element.getUid() != caller_uid) { if (element.log_id() != id || element.uid() != caller_uid) {
++it; ++it;
continue; continue;
} }
if (oldest && oldest->start() <= element.getSequence()) { if (oldest && oldest->start() <= element.sequence()) {
busy = true; busy = true;
KickReader(oldest, id, pruneRows); KickReader(oldest, id, pruneRows);
break; break;
@ -382,7 +375,7 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
bool hasBlacklist = (id != LOG_ID_SECURITY) && prune_->naughty(); bool hasBlacklist = (id != LOG_ID_SECURITY) && prune_->naughty();
while (!clearAll && (pruneRows > 0)) { while (!clearAll && (pruneRows > 0)) {
// recalculate the worst offender on every batched pass // recalculate the worst offender on every batched pass
int worst = -1; // not valid for getUid() or getKey() int worst = -1; // not valid for uid() or getKey()
size_t worst_sizes = 0; size_t worst_sizes = 0;
size_t second_worst_sizes = 0; size_t second_worst_sizes = 0;
pid_t worstPid = 0; // POSIX guarantees PID != 0 pid_t worstPid = 0; // POSIX guarantees PID != 0
@ -445,19 +438,19 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
while (it != logs().end()) { while (it != logs().end()) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
if (oldest && oldest->start() <= element.getSequence()) { if (oldest && oldest->start() <= element.sequence()) {
busy = true; busy = true;
// Do not let chatty eliding trigger any reader mitigation // Do not let chatty eliding trigger any reader mitigation
break; break;
} }
if (element.getLogId() != id) { if (element.log_id() != id) {
++it; ++it;
continue; continue;
} }
// below this point element->getLogId() == id // below this point element->log_id() == id
uint16_t dropped = element.getDropped(); uint16_t dropped = element.dropped_count();
// remove any leading drops // remove any leading drops
if (leading && dropped) { if (leading && dropped) {
@ -470,8 +463,8 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
continue; continue;
} }
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.getTag() int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.GetTag()
: element.getUid(); : element.uid();
if (hasBlacklist && prune_->naughty(&element)) { if (hasBlacklist && prune_->naughty(&element)) {
last.clear(&element); last.clear(&element);
@ -490,25 +483,25 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
if (worst_sizes < second_worst_sizes) { if (worst_sizes < second_worst_sizes) {
break; break;
} }
worst_sizes -= element.getMsgLen(); worst_sizes -= element.msg_len();
} }
continue; continue;
} }
if (element.getRealTime() < (lastt->getRealTime() - too_old) || if (element.realtime() < (lastt->realtime() - too_old) ||
element.getRealTime() > lastt->getRealTime()) { element.realtime() > lastt->realtime()) {
break; break;
} }
if (dropped) { if (dropped) {
last.add(&element); last.add(&element);
if (worstPid && ((!gc && element.getPid() == worstPid) || if (worstPid && ((!gc && element.pid() == worstPid) ||
mLastWorstPidOfSystem[id].find(element.getPid()) == mLastWorstPidOfSystem[id].find(element.pid()) ==
mLastWorstPidOfSystem[id].end())) { mLastWorstPidOfSystem[id].end())) {
// element->getUid() may not be AID_SYSTEM, next best // element->uid() may not be AID_SYSTEM, next best
// watermark if current one empty. id is not LOG_ID_EVENTS // watermark if current one empty. id is not LOG_ID_EVENTS
// or LOG_ID_SECURITY because of worstPid check. // or LOG_ID_SECURITY because of worstPid check.
mLastWorstPidOfSystem[id][element.getPid()] = it; mLastWorstPidOfSystem[id][element.pid()] = it;
} }
if ((!gc && !worstPid && (key == worst)) || if ((!gc && !worstPid && (key == worst)) ||
(mLastWorst[id].find(key) == mLastWorst[id].end())) { (mLastWorst[id].find(key) == mLastWorst[id].end())) {
@ -518,14 +511,14 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
continue; continue;
} }
if (key != worst || (worstPid && element.getPid() != worstPid)) { if (key != worst || (worstPid && element.pid() != worstPid)) {
leading = false; leading = false;
last.clear(&element); last.clear(&element);
++it; ++it;
continue; continue;
} }
// key == worst below here // key == worst below here
// If worstPid set, then element->getPid() == worstPid below here // If worstPid set, then element->pid() == worstPid below here
pruneRows--; pruneRows--;
if (pruneRows == 0) { if (pruneRows == 0) {
@ -534,21 +527,21 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
kick = true; kick = true;
uint16_t len = element.getMsgLen(); uint16_t len = element.msg_len();
// do not create any leading drops // do not create any leading drops
if (leading) { if (leading) {
it = Erase(it); it = Erase(it);
} else { } else {
stats()->Drop(&element); stats()->Drop(element);
element.setDropped(1); element.SetDropped(1);
if (last.coalesce(&element, 1)) { if (last.coalesce(&element, 1)) {
it = Erase(it, true); it = Erase(it, true);
} else { } else {
last.add(&element); last.add(&element);
if (worstPid && (!gc || mLastWorstPidOfSystem[id].find(worstPid) == if (worstPid && (!gc || mLastWorstPidOfSystem[id].find(worstPid) ==
mLastWorstPidOfSystem[id].end())) { mLastWorstPidOfSystem[id].end())) {
// element->getUid() may not be AID_SYSTEM, next best // element->uid() may not be AID_SYSTEM, next best
// watermark if current one empty. id is not // watermark if current one empty. id is not
// LOG_ID_EVENTS or LOG_ID_SECURITY because of worstPid. // LOG_ID_EVENTS or LOG_ID_SECURITY because of worstPid.
mLastWorstPidOfSystem[id][worstPid] = it; mLastWorstPidOfSystem[id][worstPid] = it;
@ -577,18 +570,18 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
while ((pruneRows > 0) && (it != logs().end())) { while ((pruneRows > 0) && (it != logs().end())) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
if (element.getLogId() != id) { if (element.log_id() != id) {
it++; it++;
continue; continue;
} }
if (oldest && oldest->start() <= element.getSequence()) { if (oldest && oldest->start() <= element.sequence()) {
busy = true; busy = true;
if (!whitelist) KickReader(oldest, id, pruneRows); if (!whitelist) KickReader(oldest, id, pruneRows);
break; break;
} }
if (hasWhitelist && !element.getDropped() && prune_->nice(&element)) { if (hasWhitelist && !element.dropped_count() && prune_->nice(&element)) {
// WhiteListed // WhiteListed
whitelist = true; whitelist = true;
it++; it++;
@ -605,12 +598,12 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
while ((it != logs().end()) && (pruneRows > 0)) { while ((it != logs().end()) && (pruneRows > 0)) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
if (element.getLogId() != id) { if (element.log_id() != id) {
++it; ++it;
continue; continue;
} }
if (oldest && oldest->start() <= element.getSequence()) { if (oldest && oldest->start() <= element.sequence()) {
busy = true; busy = true;
KickReader(oldest, id, pruneRows); KickReader(oldest, id, pruneRows);
break; break;

View file

@ -32,92 +32,92 @@
LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
pid_t tid, uint64_t sequence, const char* msg, uint16_t len) pid_t tid, uint64_t sequence, const char* msg, uint16_t len)
: mUid(uid), : uid_(uid),
mPid(pid), pid_(pid),
mTid(tid), tid_(tid),
mSequence(sequence), sequence_(sequence),
mRealTime(realtime), realtime_(realtime),
mMsgLen(len), msg_len_(len),
mLogId(log_id), log_id_(log_id),
mDropped(false) { dropped_(false) {
mMsg = new char[len]; msg_ = new char[len];
memcpy(mMsg, msg, len); memcpy(msg_, msg, len);
} }
LogBufferElement::LogBufferElement(const LogBufferElement& elem) LogBufferElement::LogBufferElement(const LogBufferElement& elem)
: mUid(elem.mUid), : uid_(elem.uid_),
mPid(elem.mPid), pid_(elem.pid_),
mTid(elem.mTid), tid_(elem.tid_),
mSequence(elem.mSequence), sequence_(elem.sequence_),
mRealTime(elem.mRealTime), realtime_(elem.realtime_),
mMsgLen(elem.mMsgLen), msg_len_(elem.msg_len_),
mLogId(elem.mLogId), log_id_(elem.log_id_),
mDropped(elem.mDropped) { dropped_(elem.dropped_) {
if (mDropped) { if (dropped_) {
mTag = elem.getTag(); tag_ = elem.GetTag();
} else { } else {
mMsg = new char[mMsgLen]; msg_ = new char[msg_len_];
memcpy(mMsg, elem.mMsg, mMsgLen); memcpy(msg_, elem.msg_, msg_len_);
} }
} }
LogBufferElement::LogBufferElement(LogBufferElement&& elem) LogBufferElement::LogBufferElement(LogBufferElement&& elem)
: mUid(elem.mUid), : uid_(elem.uid_),
mPid(elem.mPid), pid_(elem.pid_),
mTid(elem.mTid), tid_(elem.tid_),
mSequence(elem.mSequence), sequence_(elem.sequence_),
mRealTime(elem.mRealTime), realtime_(elem.realtime_),
mMsgLen(elem.mMsgLen), msg_len_(elem.msg_len_),
mLogId(elem.mLogId), log_id_(elem.log_id_),
mDropped(elem.mDropped) { dropped_(elem.dropped_) {
if (mDropped) { if (dropped_) {
mTag = elem.getTag(); tag_ = elem.GetTag();
} else { } else {
mMsg = elem.mMsg; msg_ = elem.msg_;
elem.mMsg = nullptr; elem.msg_ = nullptr;
} }
} }
LogBufferElement::~LogBufferElement() { LogBufferElement::~LogBufferElement() {
if (!mDropped) { if (!dropped_) {
delete[] mMsg; delete[] msg_;
} }
} }
uint32_t LogBufferElement::getTag() const { uint32_t LogBufferElement::GetTag() const {
// Binary buffers have no tag. // Binary buffers have no tag.
if (!isBinary()) { if (!IsBinary()) {
return 0; return 0;
} }
// Dropped messages store the tag in place of mMsg. // Dropped messages store the tag in place of msg_.
if (mDropped) { if (dropped_) {
return mTag; return tag_;
} }
// For non-dropped messages, we get the tag from the message header itself. // For non-dropped messages, we get the tag from the message header itself.
if (mMsgLen < sizeof(android_event_header_t)) { if (msg_len_ < sizeof(android_event_header_t)) {
return 0; return 0;
} }
return reinterpret_cast<const android_event_header_t*>(mMsg)->tag; return reinterpret_cast<const android_event_header_t*>(msg_)->tag;
} }
uint16_t LogBufferElement::setDropped(uint16_t value) { uint16_t LogBufferElement::SetDropped(uint16_t value) {
if (mDropped) { if (dropped_) {
return mDroppedCount = value; return dropped_count_ = value;
} }
// The tag information is saved in mMsg data, which is in a union with mTag, used after mDropped // The tag information is saved in msg_ data, which is in a union with tag_, used after dropped_
// is set to true. Therefore we save the tag value aside, delete mMsg, then set mTag to the tag // is set to true. Therefore we save the tag value aside, delete msg_, then set tag_ to the tag
// value in its place. // value in its place.
auto old_tag = getTag(); auto old_tag = GetTag();
delete[] mMsg; delete[] msg_;
mMsg = nullptr; msg_ = nullptr;
mTag = old_tag; tag_ = old_tag;
mDropped = true; dropped_ = true;
return mDroppedCount = value; return dropped_count_ = value;
} }
// caller must own and free character string // caller must own and free character string
@ -165,8 +165,8 @@ char* android::tidToName(pid_t tid) {
return retval; return retval;
} }
// assumption: mMsg == NULL // assumption: msg_ == NULL
size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* stats, size_t LogBufferElement::PopulateDroppedMessage(char*& buffer, LogStatistics* stats,
bool lastSame) { bool lastSame) {
static const char tag[] = "chatty"; static const char tag[] = "chatty";
@ -176,13 +176,13 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* st
} }
static const char format_uid[] = "uid=%u%s%s %s %u line%s"; static const char format_uid[] = "uid=%u%s%s %s %u line%s";
const char* name = stats->UidToName(mUid); const char* name = stats->UidToName(uid_);
const char* commName = android::tidToName(mTid); const char* commName = android::tidToName(tid_);
if (!commName && (mTid != mPid)) { if (!commName && (tid_ != pid_)) {
commName = android::tidToName(mPid); commName = android::tidToName(pid_);
} }
if (!commName) { if (!commName) {
commName = stats->PidToName(mPid); commName = stats->PidToName(pid_);
} }
if (name && name[0] && commName && (name[0] == commName[0])) { if (name && name[0] && commName && (name[0] == commName[0])) {
size_t len = strlen(name + 1); size_t len = strlen(name + 1);
@ -214,12 +214,11 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* st
} }
// identical to below to calculate the buffer size required // identical to below to calculate the buffer size required
const char* type = lastSame ? "identical" : "expire"; const char* type = lastSame ? "identical" : "expire";
size_t len = snprintf(nullptr, 0, format_uid, mUid, name ? name : "", size_t len = snprintf(nullptr, 0, format_uid, uid_, name ? name : "", commName ? commName : "",
commName ? commName : "", type, getDropped(), type, dropped_count(), (dropped_count() > 1) ? "s" : "");
(getDropped() > 1) ? "s" : "");
size_t hdrLen; size_t hdrLen;
if (isBinary()) { if (IsBinary()) {
hdrLen = sizeof(android_log_event_string_t); hdrLen = sizeof(android_log_event_string_t);
} else { } else {
hdrLen = 1 + sizeof(tag); hdrLen = 1 + sizeof(tag);
@ -233,7 +232,7 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* st
} }
size_t retval = hdrLen + len; size_t retval = hdrLen + len;
if (isBinary()) { if (IsBinary()) {
android_log_event_string_t* event = android_log_event_string_t* event =
reinterpret_cast<android_log_event_string_t*>(buffer); reinterpret_cast<android_log_event_string_t*>(buffer);
@ -246,9 +245,8 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* st
strcpy(buffer + 1, tag); strcpy(buffer + 1, tag);
} }
snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "", snprintf(buffer + hdrLen, len + 1, format_uid, uid_, name ? name : "", commName ? commName : "",
commName ? commName : "", type, getDropped(), type, dropped_count(), (dropped_count() > 1) ? "s" : "");
(getDropped() > 1) ? "s" : "");
free(const_cast<char*>(name)); free(const_cast<char*>(name));
free(const_cast<char*>(commName)); free(const_cast<char*>(commName));
@ -259,22 +257,22 @@ bool LogBufferElement::FlushTo(LogWriter* writer, LogStatistics* stats, bool las
struct logger_entry entry = {}; struct logger_entry entry = {};
entry.hdr_size = sizeof(struct logger_entry); entry.hdr_size = sizeof(struct logger_entry);
entry.lid = mLogId; entry.lid = log_id_;
entry.pid = mPid; entry.pid = pid_;
entry.tid = mTid; entry.tid = tid_;
entry.uid = mUid; entry.uid = uid_;
entry.sec = mRealTime.tv_sec; entry.sec = realtime_.tv_sec;
entry.nsec = mRealTime.tv_nsec; entry.nsec = realtime_.tv_nsec;
char* buffer = nullptr; char* buffer = nullptr;
const char* msg; const char* msg;
if (mDropped) { if (dropped_) {
entry.len = populateDroppedMessage(buffer, stats, lastSame); entry.len = PopulateDroppedMessage(buffer, stats, lastSame);
if (!entry.len) return true; if (!entry.len) return true;
msg = buffer; msg = buffer;
} else { } else {
msg = mMsg; msg = msg_;
entry.len = mMsgLen; entry.len = msg_len_;
} }
bool retval = writer->Write(entry, msg); bool retval = writer->Write(entry, msg);

View file

@ -33,26 +33,6 @@ class LogStatistics;
#define EXPIRE_RATELIMIT 10 // maximum rate in seconds to report expiration #define EXPIRE_RATELIMIT 10 // maximum rate in seconds to report expiration
class __attribute__((packed)) LogBufferElement { class __attribute__((packed)) LogBufferElement {
// sized to match reality of incoming log packets
const uint32_t mUid;
const uint32_t mPid;
const uint32_t mTid;
uint64_t mSequence;
log_time mRealTime;
union {
char* mMsg; // mDropped == false
int32_t mTag; // mDropped == true
};
union {
const uint16_t mMsgLen; // mDropped == false
uint16_t mDroppedCount; // mDropped == true
};
const uint8_t mLogId;
bool mDropped;
// assumption: mDropped == true
size_t populateDroppedMessage(char*& buffer, LogStatistics* parent, bool lastSame);
public: public:
LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
uint64_t sequence, const char* msg, uint16_t len); uint64_t sequence, const char* msg, uint16_t len);
@ -60,37 +40,41 @@ class __attribute__((packed)) LogBufferElement {
LogBufferElement(LogBufferElement&& elem); LogBufferElement(LogBufferElement&& elem);
~LogBufferElement(); ~LogBufferElement();
bool isBinary(void) const { bool IsBinary() const { return (log_id_ == LOG_ID_EVENTS) || (log_id_ == LOG_ID_SECURITY); }
return (mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY);
}
log_id_t getLogId() const { uint32_t GetTag() const;
return static_cast<log_id_t>(mLogId); uint16_t SetDropped(uint16_t value);
}
uid_t getUid(void) const {
return mUid;
}
pid_t getPid(void) const {
return mPid;
}
pid_t getTid(void) const {
return mTid;
}
uint32_t getTag() const;
uint16_t getDropped(void) const {
return mDropped ? mDroppedCount : 0;
}
uint16_t setDropped(uint16_t value);
uint16_t getMsgLen() const {
return mDropped ? 0 : mMsgLen;
}
const char* getMsg() const {
return mDropped ? nullptr : mMsg;
}
uint64_t getSequence() const { return mSequence; }
log_time getRealTime(void) const {
return mRealTime;
}
bool FlushTo(LogWriter* writer, LogStatistics* parent, bool lastSame); bool FlushTo(LogWriter* writer, LogStatistics* parent, bool lastSame);
log_id_t log_id() const { return static_cast<log_id_t>(log_id_); }
uid_t uid() const { return uid_; }
pid_t pid() const { return pid_; }
pid_t tid() const { return tid_; }
uint16_t msg_len() const { return dropped_ ? 0 : msg_len_; }
const char* msg() const { return dropped_ ? nullptr : msg_; }
uint64_t sequence() const { return sequence_; }
log_time realtime() const { return realtime_; }
uint16_t dropped_count() const { return dropped_ ? dropped_count_ : 0; }
private:
// assumption: mDropped == true
size_t PopulateDroppedMessage(char*& buffer, LogStatistics* parent, bool lastSame);
// sized to match reality of incoming log packets
const uint32_t uid_;
const uint32_t pid_;
const uint32_t tid_;
uint64_t sequence_;
log_time realtime_;
union {
char* msg_; // mDropped == false
int32_t tag_; // mDropped == true
};
union {
const uint16_t msg_len_; // mDropped == false
uint16_t dropped_count_; // mDropped == true
};
const uint8_t log_id_;
bool dropped_;
}; };

View file

@ -87,10 +87,10 @@ void LogStatistics::AddTotal(log_id_t log_id, uint16_t size) {
++mElementsTotal[log_id]; ++mElementsTotal[log_id];
} }
void LogStatistics::Add(LogBufferElement* element) { void LogStatistics::Add(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_}; auto lock = std::lock_guard{lock_};
log_id_t log_id = element->getLogId(); log_id_t log_id = element.log_id();
uint16_t size = element->getMsgLen(); uint16_t size = element.msg_len();
mSizes[log_id] += size; mSizes[log_id] += size;
++mElements[log_id]; ++mElements[log_id];
@ -99,7 +99,7 @@ void LogStatistics::Add(LogBufferElement* element) {
// evaluated and trimmed, thus recording size and number of // evaluated and trimmed, thus recording size and number of
// elements, but we must recognize the manufactured dropped // elements, but we must recognize the manufactured dropped
// entry as not contributing to the lifetime totals. // entry as not contributing to the lifetime totals.
if (element->getDropped()) { if (element.dropped_count()) {
++mDroppedElements[log_id]; ++mDroppedElements[log_id];
} else { } else {
mSizesTotal[log_id] += size; mSizesTotal[log_id] += size;
@ -107,7 +107,7 @@ void LogStatistics::Add(LogBufferElement* element) {
++mElementsTotal[log_id]; ++mElementsTotal[log_id];
} }
log_time stamp(element->getRealTime()); log_time stamp(element.realtime());
if (mNewest[log_id] < stamp) { if (mNewest[log_id] < stamp) {
// A major time update invalidates the statistics :-( // A major time update invalidates the statistics :-(
log_time diff = stamp - mNewest[log_id]; log_time diff = stamp - mNewest[log_id];
@ -132,111 +132,111 @@ void LogStatistics::Add(LogBufferElement* element) {
return; return;
} }
uidTable[log_id].add(element->getUid(), element); uidTable[log_id].Add(element.uid(), element);
if (element->getUid() == AID_SYSTEM) { if (element.uid() == AID_SYSTEM) {
pidSystemTable[log_id].add(element->getPid(), element); pidSystemTable[log_id].Add(element.pid(), element);
} }
if (!enable) { if (!enable) {
return; return;
} }
pidTable.add(element->getPid(), element); pidTable.Add(element.pid(), element);
tidTable.add(element->getTid(), element); tidTable.Add(element.tid(), element);
uint32_t tag = element->getTag(); uint32_t tag = element.GetTag();
if (tag) { if (tag) {
if (log_id == LOG_ID_SECURITY) { if (log_id == LOG_ID_SECURITY) {
securityTagTable.add(tag, element); securityTagTable.Add(tag, element);
} else { } else {
tagTable.add(tag, element); tagTable.Add(tag, element);
} }
} }
if (!element->getDropped()) { if (!element.dropped_count()) {
tagNameTable.add(TagNameKey(element), element); tagNameTable.Add(TagNameKey(element), element);
} }
} }
void LogStatistics::Subtract(LogBufferElement* element) { void LogStatistics::Subtract(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_}; auto lock = std::lock_guard{lock_};
log_id_t log_id = element->getLogId(); log_id_t log_id = element.log_id();
uint16_t size = element->getMsgLen(); uint16_t size = element.msg_len();
mSizes[log_id] -= size; mSizes[log_id] -= size;
--mElements[log_id]; --mElements[log_id];
if (element->getDropped()) { if (element.dropped_count()) {
--mDroppedElements[log_id]; --mDroppedElements[log_id];
} }
if (mOldest[log_id] < element->getRealTime()) { if (mOldest[log_id] < element.realtime()) {
mOldest[log_id] = element->getRealTime(); mOldest[log_id] = element.realtime();
} }
if (log_id == LOG_ID_KERNEL) { if (log_id == LOG_ID_KERNEL) {
return; return;
} }
uidTable[log_id].subtract(element->getUid(), element); uidTable[log_id].Subtract(element.uid(), element);
if (element->getUid() == AID_SYSTEM) { if (element.uid() == AID_SYSTEM) {
pidSystemTable[log_id].subtract(element->getPid(), element); pidSystemTable[log_id].Subtract(element.pid(), element);
} }
if (!enable) { if (!enable) {
return; return;
} }
pidTable.subtract(element->getPid(), element); pidTable.Subtract(element.pid(), element);
tidTable.subtract(element->getTid(), element); tidTable.Subtract(element.tid(), element);
uint32_t tag = element->getTag(); uint32_t tag = element.GetTag();
if (tag) { if (tag) {
if (log_id == LOG_ID_SECURITY) { if (log_id == LOG_ID_SECURITY) {
securityTagTable.subtract(tag, element); securityTagTable.Subtract(tag, element);
} else { } else {
tagTable.subtract(tag, element); tagTable.Subtract(tag, element);
} }
} }
if (!element->getDropped()) { if (!element.dropped_count()) {
tagNameTable.subtract(TagNameKey(element), element); tagNameTable.Subtract(TagNameKey(element), element);
} }
} }
// Atomically set an entry to drop // Atomically set an entry to drop
// entry->setDropped(1) must follow this call, caller should do this explicitly. // entry->setDropped(1) must follow this call, caller should do this explicitly.
void LogStatistics::Drop(LogBufferElement* element) { void LogStatistics::Drop(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_}; auto lock = std::lock_guard{lock_};
log_id_t log_id = element->getLogId(); log_id_t log_id = element.log_id();
uint16_t size = element->getMsgLen(); uint16_t size = element.msg_len();
mSizes[log_id] -= size; mSizes[log_id] -= size;
++mDroppedElements[log_id]; ++mDroppedElements[log_id];
if (mNewestDropped[log_id] < element->getRealTime()) { if (mNewestDropped[log_id] < element.realtime()) {
mNewestDropped[log_id] = element->getRealTime(); mNewestDropped[log_id] = element.realtime();
} }
uidTable[log_id].drop(element->getUid(), element); uidTable[log_id].Drop(element.uid(), element);
if (element->getUid() == AID_SYSTEM) { if (element.uid() == AID_SYSTEM) {
pidSystemTable[log_id].drop(element->getPid(), element); pidSystemTable[log_id].Drop(element.pid(), element);
} }
if (!enable) { if (!enable) {
return; return;
} }
pidTable.drop(element->getPid(), element); pidTable.Drop(element.pid(), element);
tidTable.drop(element->getTid(), element); tidTable.Drop(element.tid(), element);
uint32_t tag = element->getTag(); uint32_t tag = element.GetTag();
if (tag) { if (tag) {
if (log_id == LOG_ID_SECURITY) { if (log_id == LOG_ID_SECURITY) {
securityTagTable.drop(tag, element); securityTagTable.Drop(tag, element);
} else { } else {
tagTable.drop(tag, element); tagTable.Drop(tag, element);
} }
} }
tagNameTable.subtract(TagNameKey(element), element); tagNameTable.Subtract(TagNameKey(element), element);
} }
const char* LogStatistics::UidToName(uid_t uid) const { const char* LogStatistics::UidToName(uid_t uid) const {
@ -283,8 +283,8 @@ const char* LogStatistics::UidToNameLocked(uid_t uid) const {
++it) { ++it) {
const PidEntry& entry = it->second; const PidEntry& entry = it->second;
if (entry.getUid() == uid) { if (entry.uid() == uid) {
const char* nameTmp = entry.getName(); const char* nameTmp = entry.name();
if (nameTmp) { if (nameTmp) {
if (!name) { if (!name) {
@ -314,8 +314,8 @@ void LogStatistics::WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& tabl
*worst_sizes = max_entries[0]->getSizes(); *worst_sizes = max_entries[0]->getSizes();
// b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is // b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
// 100 characters. // 100 characters.
if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->getDropped())) { if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->dropped_count())) {
*worst = max_entries[0]->getKey(); *worst = max_entries[0]->key();
*second_worst_sizes = max_entries[1]->getSizes(); *second_worst_sizes = max_entries[1]->getSizes();
if (*second_worst_sizes < threshold) { if (*second_worst_sizes < threshold) {
*second_worst_sizes = threshold; *second_worst_sizes = threshold;
@ -344,7 +344,7 @@ void LogStatistics::WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* w
return; return;
} }
*worst = max_entries[0]->getKey(); *worst = max_entries[0]->key();
*second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes(); *second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes();
} }
@ -393,9 +393,8 @@ void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name,
if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid); if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid);
if (nameTmp) { if (nameTmp) {
size_t lenSpace = std::max(nameLen - name.length(), (size_t)1); size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
size_t len = EntryBaseConstants::total_len - size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
EntryBaseConstants::pruned_len - size.length() - lenSpace - 2;
name.length() - lenSpace - 2;
size_t lenNameTmp = strlen(nameTmp); size_t lenNameTmp = strlen(nameTmp);
while ((len < lenNameTmp) && (lenSpace > 1)) { while ((len < lenNameTmp) && (lenSpace > 1)) {
++len; ++len;
@ -412,11 +411,10 @@ void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name,
} }
std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUIRES(stat.lock_) { std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUIRES(stat.lock_) {
uid_t uid = getUid(); std::string name = android::base::StringPrintf("%u", uid_);
std::string name = android::base::StringPrintf("%u", uid);
std::string size = android::base::StringPrintf("%zu", getSizes()); std::string size = android::base::StringPrintf("%zu", getSizes());
stat.FormatTmp(nullptr, uid, name, size, 6); stat.FormatTmp(nullptr, uid_, name, size, 6);
std::string pruned = ""; std::string pruned = "";
if (worstUidEnabledForLogid(id)) { if (worstUidEnabledForLogid(id)) {
@ -424,7 +422,7 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI
for (LogStatistics::uidTable_t::const_iterator it = for (LogStatistics::uidTable_t::const_iterator it =
stat.uidTable[id].begin(); stat.uidTable[id].begin();
it != stat.uidTable[id].end(); ++it) { it != stat.uidTable[id].end(); ++it) {
totalDropped += it->second.getDropped(); totalDropped += it->second.dropped_count();
} }
size_t sizes = stat.mSizes[id]; size_t sizes = stat.mSizes[id];
size_t totalSize = stat.mSizesTotal[id]; size_t totalSize = stat.mSizesTotal[id];
@ -434,7 +432,7 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI
size_t entrySize = getSizes(); size_t entrySize = getSizes();
float virtualEntrySize = entrySize; float virtualEntrySize = entrySize;
int realPermille = virtualEntrySize * 1000.0 / sizes; int realPermille = virtualEntrySize * 1000.0 / sizes;
size_t dropped = getDropped(); size_t dropped = dropped_count();
if (dropped) { if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped); pruned = android::base::StringPrintf("%zu", dropped);
virtualEntrySize += (float)dropped * totalSize / totalElements; virtualEntrySize += (float)dropped * totalSize / totalElements;
@ -461,8 +459,7 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI
change = android::base::StringPrintf( change = android::base::StringPrintf(
"%s%d%s", prefix, (permille + 5) / 10, units); "%s%d%s", prefix, (permille + 5) / 10, units);
} }
ssize_t spaces = EntryBaseConstants::pruned_len - 2 - ssize_t spaces = EntryBase::PRUNED_LEN - 2 - pruned.length() - change.length();
pruned.length() - change.length();
if ((spaces <= 0) && pruned.length()) { if ((spaces <= 0) && pruned.length()) {
spaces = 1; spaces = 1;
} }
@ -475,13 +472,13 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI
std::string output = formatLine(name, size, pruned); std::string output = formatLine(name, size, pruned);
if (uid != AID_SYSTEM) { if (uid_ != AID_SYSTEM) {
return output; return output;
} }
static const size_t maximum_sorted_entries = 32; static const size_t maximum_sorted_entries = 32;
std::array<const PidEntry*, maximum_sorted_entries> sorted; std::array<const PidEntry*, maximum_sorted_entries> sorted;
stat.pidSystemTable[id].MaxEntries(uid, 0, &sorted); stat.pidSystemTable[id].MaxEntries(uid_, 0, &sorted);
std::string byPid; std::string byPid;
size_t index; size_t index;
@ -494,7 +491,7 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI
if (entry->getSizes() <= (getSizes() / 100)) { if (entry->getSizes() <= (getSizes() / 100)) {
break; break;
} }
if (entry->getDropped()) { if (entry->dropped_count()) {
hasDropped = true; hasDropped = true;
} }
byPid += entry->format(stat, id); byPid += entry->format(stat, id);
@ -518,15 +515,13 @@ std::string PidEntry::formatHeader(const std::string& name,
std::string PidEntry::format(const LogStatistics& stat, log_id_t /* id */) const std::string PidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
REQUIRES(stat.lock_) { REQUIRES(stat.lock_) {
uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", pid_, uid_);
pid_t pid = getPid();
std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
std::string size = android::base::StringPrintf("%zu", getSizes()); std::string size = android::base::StringPrintf("%zu", getSizes());
stat.FormatTmp(getName(), uid, name, size, 12); stat.FormatTmp(name_, uid_, name, size, 12);
std::string pruned = ""; std::string pruned = "";
size_t dropped = getDropped(); size_t dropped = dropped_count();
if (dropped) { if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped); pruned = android::base::StringPrintf("%zu", dropped);
} }
@ -543,14 +538,13 @@ std::string TidEntry::formatHeader(const std::string& name,
std::string TidEntry::format(const LogStatistics& stat, log_id_t /* id */) const std::string TidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
REQUIRES(stat.lock_) { REQUIRES(stat.lock_) {
uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", tid(), uid_);
std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
std::string size = android::base::StringPrintf("%zu", getSizes()); std::string size = android::base::StringPrintf("%zu", getSizes());
stat.FormatTmp(getName(), uid, name, size, 12); stat.FormatTmp(name_, uid_, name, size, 12);
std::string pruned = ""; std::string pruned = "";
size_t dropped = getDropped(); size_t dropped = dropped_count();
if (dropped) { if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped); pruned = android::base::StringPrintf("%zu", dropped);
} }
@ -569,13 +563,12 @@ std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
std::string TagEntry::format(const LogStatistics& /* stat */, std::string TagEntry::format(const LogStatistics& /* stat */,
log_id_t /* id */) const { log_id_t /* id */) const {
std::string name; std::string name;
uid_t uid = getUid(); if (uid_ == (uid_t)-1) {
if (uid == (uid_t)-1) { name = android::base::StringPrintf("%7u", key());
name = android::base::StringPrintf("%7u", getKey());
} else { } else {
name = android::base::StringPrintf("%7u/%u", getKey(), uid); name = android::base::StringPrintf("%7u/%u", key(), uid_);
} }
const char* nameTmp = getName(); const char* nameTmp = this->name();
if (nameTmp) { if (nameTmp) {
name += android::base::StringPrintf( name += android::base::StringPrintf(
"%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp); "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
@ -584,7 +577,7 @@ std::string TagEntry::format(const LogStatistics& /* stat */,
std::string size = android::base::StringPrintf("%zu", getSizes()); std::string size = android::base::StringPrintf("%zu", getSizes());
std::string pruned = ""; std::string pruned = "";
size_t dropped = getDropped(); size_t dropped = dropped_count();
if (dropped) { if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped); pruned = android::base::StringPrintf("%zu", dropped);
} }
@ -602,34 +595,30 @@ std::string TagNameEntry::formatHeader(const std::string& name,
std::string TagNameEntry::format(const LogStatistics& /* stat */, std::string TagNameEntry::format(const LogStatistics& /* stat */,
log_id_t /* id */) const { log_id_t /* id */) const {
std::string name; std::string name;
pid_t tid = getTid();
pid_t pid = getPid();
std::string pidstr; std::string pidstr;
if (pid != (pid_t)-1) { if (pid_ != (pid_t)-1) {
pidstr = android::base::StringPrintf("%u", pid); pidstr = android::base::StringPrintf("%u", pid_);
if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr; if (tid_ != (pid_t)-1 && tid_ != pid_) pidstr = "/" + pidstr;
} }
int len = 9 - pidstr.length(); int len = 9 - pidstr.length();
if (len < 0) len = 0; if (len < 0) len = 0;
if ((tid == (pid_t)-1) || (tid == pid)) { if (tid_ == (pid_t)-1 || tid_ == pid_) {
name = android::base::StringPrintf("%*s", len, ""); name = android::base::StringPrintf("%*s", len, "");
} else { } else {
name = android::base::StringPrintf("%*u", len, tid); name = android::base::StringPrintf("%*u", len, tid_);
} }
name += pidstr; name += pidstr;
uid_t uid = getUid(); if (uid_ != (uid_t)-1) {
if (uid != (uid_t)-1) { name += android::base::StringPrintf("/%u", uid_);
name += android::base::StringPrintf("/%u", uid);
} }
std::string size = android::base::StringPrintf("%zu", getSizes()); std::string size = android::base::StringPrintf("%zu", getSizes());
const char* nameTmp = getName(); const char* nameTmp = this->name();
if (nameTmp) { if (nameTmp) {
size_t lenSpace = std::max(16 - name.length(), (size_t)1); size_t lenSpace = std::max(16 - name.length(), (size_t)1);
size_t len = EntryBaseConstants::total_len - size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
EntryBaseConstants::pruned_len - size.length() - lenSpace - 2;
name.length() - lenSpace - 2;
size_t lenNameTmp = strlen(nameTmp); size_t lenNameTmp = strlen(nameTmp);
while ((len < lenNameTmp) && (lenSpace > 1)) { while ((len < lenNameTmp) && (lenSpace > 1)) {
++len; ++len;
@ -944,7 +933,7 @@ uid_t pidToUid(pid_t pid) {
uid_t LogStatistics::PidToUid(pid_t pid) { uid_t LogStatistics::PidToUid(pid_t pid) {
auto lock = std::lock_guard{lock_}; auto lock = std::lock_guard{lock_};
return pidTable.add(pid)->second.getUid(); return pidTable.Add(pid)->second.uid();
} }
// caller must free character string // caller must free character string
@ -952,7 +941,7 @@ const char* LogStatistics::PidToName(pid_t pid) const {
auto lock = std::lock_guard{lock_}; auto lock = std::lock_guard{lock_};
// An inconvenient truth ... getName() can alter the object // An inconvenient truth ... getName() can alter the object
pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable); pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
const char* name = writablePidTable.add(pid)->second.getName(); const char* name = writablePidTable.Add(pid)->second.name();
if (!name) { if (!name) {
return nullptr; return nullptr;
} }

View file

@ -65,7 +65,7 @@ class LogHashtable {
static const size_t unordered_map_per_entry_overhead = sizeof(void*); static const size_t unordered_map_per_entry_overhead = sizeof(void*);
static const size_t unordered_map_bucket_overhead = sizeof(void*); static const size_t unordered_map_bucket_overhead = sizeof(void*);
public: public:
size_t size() const { size_t size() const {
return map.size(); return map.size();
} }
@ -90,10 +90,10 @@ class LogHashtable {
for (const_iterator it = map.begin(); it != map.end(); ++it) { for (const_iterator it = map.begin(); it != map.end(); ++it) {
const TEntry& entry = it->second; const TEntry& entry = it->second;
if ((uid != AID_ROOT) && (uid != entry.getUid())) { if (uid != AID_ROOT && uid != entry.uid()) {
continue; continue;
} }
if (pid && entry.getPid() && (pid != entry.getPid())) { if (pid && entry.pid() && pid != entry.pid()) {
continue; continue;
} }
@ -113,95 +113,67 @@ class LogHashtable {
} }
} }
inline iterator add(const TKey& key, const LogBufferElement* element) { iterator Add(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key); iterator it = map.find(key);
if (it == map.end()) { if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(element))).first; it = map.insert(std::make_pair(key, TEntry(element))).first;
} else { } else {
it->second.add(element); it->second.Add(element);
} }
return it; return it;
} }
inline iterator add(TKey key) { iterator Add(const TKey& key) {
iterator it = map.find(key); iterator it = map.find(key);
if (it == map.end()) { if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(key))).first; it = map.insert(std::make_pair(key, TEntry(key))).first;
} else { } else {
it->second.add(key); it->second.Add(key);
} }
return it; return it;
} }
void subtract(TKey&& key, const LogBufferElement* element) { void Subtract(const 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); iterator it = map.find(key);
if ((it != map.end()) && it->second.subtract(element)) { if (it != map.end() && it->second.Subtract(element)) {
map.erase(it); map.erase(it);
} }
} }
inline void drop(TKey key, const LogBufferElement* element) { void Drop(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key); iterator it = map.find(key);
if (it != map.end()) { if (it != map.end()) {
it->second.drop(element); it->second.Drop(element);
} }
} }
inline iterator begin() { iterator begin() { return map.begin(); }
return map.begin(); const_iterator begin() const { return map.begin(); }
} iterator end() { return map.end(); }
inline const_iterator begin() const { const_iterator end() const { return map.end(); }
return map.begin();
}
inline iterator end() {
return map.end();
}
inline const_iterator end() const {
return map.end();
}
}; };
namespace EntryBaseConstants { class EntryBase {
static constexpr size_t pruned_len = 14; public:
static constexpr size_t total_len = 80; EntryBase() : size_(0) {}
} explicit EntryBase(const LogBufferElement& element) : size_(element.msg_len()) {}
struct EntryBase { size_t getSizes() const { return size_; }
size_t size;
EntryBase() : size(0) { void Add(const LogBufferElement& element) { size_ += element.msg_len(); }
} bool Subtract(const LogBufferElement& element) {
explicit EntryBase(const LogBufferElement* element) size_ -= element.msg_len();
: size(element->getMsgLen()) { return !size_;
} }
size_t getSizes() const { static constexpr size_t PRUNED_LEN = 14;
return size; static constexpr size_t TOTAL_LEN = 80;
}
inline void add(const LogBufferElement* element) {
size += element->getMsgLen();
}
inline bool subtract(const LogBufferElement* element) {
size -= element->getMsgLen();
return !size;
}
static std::string formatLine(const std::string& name, static std::string formatLine(const std::string& name,
const std::string& size, const std::string& size,
const std::string& pruned) { const std::string& pruned) {
ssize_t drop_len = ssize_t drop_len = std::max(pruned.length() + 1, PRUNED_LEN);
std::max(pruned.length() + 1, EntryBaseConstants::pruned_len); ssize_t size_len = std::max(size.length() + 1, TOTAL_LEN - name.length() - drop_len - 1);
ssize_t size_len =
std::max(size.length() + 1, EntryBaseConstants::total_len -
name.length() - drop_len - 1);
std::string ret = android::base::StringPrintf( std::string ret = android::base::StringPrintf(
"%s%*s%*s", name.c_str(), (int)size_len, size.c_str(), "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
@ -213,258 +185,220 @@ struct EntryBase {
if (len) ret.erase(pos + 1, len); if (len) ret.erase(pos + 1, len);
return ret + "\n"; return ret + "\n";
} }
private:
size_t size_;
}; };
struct EntryBaseDropped : public EntryBase { class EntryBaseDropped : public EntryBase {
size_t dropped; public:
EntryBaseDropped() : dropped_(0) {}
explicit EntryBaseDropped(const LogBufferElement& element)
: EntryBase(element), dropped_(element.dropped_count()) {}
EntryBaseDropped() : dropped(0) { size_t dropped_count() const { return dropped_; }
void Add(const LogBufferElement& element) {
dropped_ += element.dropped_count();
EntryBase::Add(element);
} }
explicit EntryBaseDropped(const LogBufferElement* element) bool Subtract(const LogBufferElement& element) {
: EntryBase(element), dropped(element->getDropped()) { dropped_ -= element.dropped_count();
return EntryBase::Subtract(element) && !dropped_;
}
void Drop(const LogBufferElement& element) {
dropped_ += 1;
EntryBase::Subtract(element);
} }
size_t getDropped() const { private:
return dropped; size_t dropped_;
}
inline void add(const LogBufferElement* element) {
dropped += element->getDropped();
EntryBase::add(element);
}
inline bool subtract(const LogBufferElement* element) {
dropped -= element->getDropped();
return EntryBase::subtract(element) && !dropped;
}
inline void drop(const LogBufferElement* element) {
dropped += 1;
EntryBase::subtract(element);
}
}; };
struct UidEntry : public EntryBaseDropped { class UidEntry : public EntryBaseDropped {
const uid_t uid; public:
pid_t pid; explicit UidEntry(const LogBufferElement& element)
: EntryBaseDropped(element), uid_(element.uid()), pid_(element.pid()) {}
explicit UidEntry(const LogBufferElement* element) uid_t key() const { return uid_; }
: EntryBaseDropped(element), uid_t uid() const { return key(); }
uid(element->getUid()), pid_t pid() const { return pid_; }
pid(element->getPid()) {
}
inline const uid_t& getKey() const { void Add(const LogBufferElement& element) {
return uid; if (pid_ != element.pid()) {
} pid_ = -1;
inline const uid_t& getUid() const {
return getKey();
}
inline const pid_t& getPid() const {
return pid;
}
inline void add(const LogBufferElement* element) {
if (pid != element->getPid()) {
pid = -1;
} }
EntryBaseDropped::add(element); EntryBaseDropped::Add(element);
} }
std::string formatHeader(const std::string& name, log_id_t id) const; std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const;
private:
const uid_t uid_;
pid_t pid_;
}; };
namespace android { namespace android {
uid_t pidToUid(pid_t pid); uid_t pidToUid(pid_t pid);
} }
struct PidEntry : public EntryBaseDropped { class PidEntry : public EntryBaseDropped {
const pid_t pid; public:
uid_t uid;
char* name;
explicit PidEntry(pid_t pid) explicit PidEntry(pid_t pid)
: EntryBaseDropped(), : EntryBaseDropped(),
pid(pid), pid_(pid),
uid(android::pidToUid(pid)), uid_(android::pidToUid(pid)),
name(android::pidToName(pid)) { name_(android::pidToName(pid)) {}
} explicit PidEntry(const LogBufferElement& element)
explicit PidEntry(const LogBufferElement* element)
: EntryBaseDropped(element), : EntryBaseDropped(element),
pid(element->getPid()), pid_(element.pid()),
uid(element->getUid()), uid_(element.uid()),
name(android::pidToName(pid)) { name_(android::pidToName(pid_)) {}
}
PidEntry(const PidEntry& element) PidEntry(const PidEntry& element)
: EntryBaseDropped(element), : EntryBaseDropped(element),
pid(element.pid), pid_(element.pid_),
uid(element.uid), uid_(element.uid_),
name(element.name ? strdup(element.name) : nullptr) { name_(element.name_ ? strdup(element.name_) : nullptr) {}
} ~PidEntry() { free(name_); }
~PidEntry() {
free(name);
}
const pid_t& getKey() const { pid_t key() const { return pid_; }
return pid; pid_t pid() const { return key(); }
} uid_t uid() const { return uid_; }
const pid_t& getPid() const { const char* name() const { return name_; }
return getKey();
}
const uid_t& getUid() const {
return uid;
}
const char* getName() const {
return name;
}
inline void add(pid_t newPid) { void Add(pid_t new_pid) {
if (name && !fastcmp<strncmp>(name, "zygote", 6)) { if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
free(name); free(name_);
name = nullptr; name_ = nullptr;
} }
if (!name) { if (!name_) {
name = android::pidToName(newPid); name_ = android::pidToName(new_pid);
} }
} }
inline void add(const LogBufferElement* element) { void Add(const LogBufferElement& element) {
uid_t incomingUid = element->getUid(); uid_t incoming_uid = element.uid();
if (getUid() != incomingUid) { if (uid() != incoming_uid) {
uid = incomingUid; uid_ = incoming_uid;
free(name); free(name_);
name = android::pidToName(element->getPid()); name_ = android::pidToName(element.pid());
} else { } else {
add(element->getPid()); Add(element.pid());
} }
EntryBaseDropped::add(element); EntryBaseDropped::Add(element);
} }
std::string formatHeader(const std::string& name, log_id_t id) const; std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const;
private:
const pid_t pid_;
uid_t uid_;
char* name_;
}; };
struct TidEntry : public EntryBaseDropped { class TidEntry : public EntryBaseDropped {
const pid_t tid; public:
pid_t pid;
uid_t uid;
char* name;
TidEntry(pid_t tid, pid_t pid) TidEntry(pid_t tid, pid_t pid)
: EntryBaseDropped(), : EntryBaseDropped(),
tid(tid), tid_(tid),
pid(pid), pid_(pid),
uid(android::pidToUid(tid)), uid_(android::pidToUid(tid)),
name(android::tidToName(tid)) { name_(android::tidToName(tid)) {}
} explicit TidEntry(const LogBufferElement& element)
explicit TidEntry(const LogBufferElement* element)
: EntryBaseDropped(element), : EntryBaseDropped(element),
tid(element->getTid()), tid_(element.tid()),
pid(element->getPid()), pid_(element.pid()),
uid(element->getUid()), uid_(element.uid()),
name(android::tidToName(tid)) { name_(android::tidToName(tid_)) {}
}
TidEntry(const TidEntry& element) TidEntry(const TidEntry& element)
: EntryBaseDropped(element), : EntryBaseDropped(element),
tid(element.tid), tid_(element.tid_),
pid(element.pid), pid_(element.pid_),
uid(element.uid), uid_(element.uid_),
name(element.name ? strdup(element.name) : nullptr) { name_(element.name_ ? strdup(element.name_) : nullptr) {}
} ~TidEntry() { free(name_); }
~TidEntry() {
free(name);
}
const pid_t& getKey() const { pid_t key() const { return tid_; }
return tid; pid_t tid() const { return key(); }
} pid_t pid() const { return pid_; }
const pid_t& getTid() const { uid_t uid() const { return uid_; }
return getKey(); const char* name() const { return name_; }
}
const pid_t& getPid() const {
return pid;
}
const uid_t& getUid() const {
return uid;
}
const char* getName() const {
return name;
}
inline void add(pid_t incomingTid) { void Add(pid_t incomingTid) {
if (name && !fastcmp<strncmp>(name, "zygote", 6)) { if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
free(name); free(name_);
name = nullptr; name_ = nullptr;
} }
if (!name) { if (!name_) {
name = android::tidToName(incomingTid); name_ = android::tidToName(incomingTid);
} }
} }
inline void add(const LogBufferElement* element) { void Add(const LogBufferElement& element) {
uid_t incomingUid = element->getUid(); uid_t incoming_uid = element.uid();
pid_t incomingPid = element->getPid(); pid_t incoming_pid = element.pid();
if ((getUid() != incomingUid) || (getPid() != incomingPid)) { if (uid() != incoming_uid || pid() != incoming_pid) {
uid = incomingUid; uid_ = incoming_uid;
pid = incomingPid; pid_ = incoming_pid;
free(name); free(name_);
name = android::tidToName(element->getTid()); name_ = android::tidToName(element.tid());
} else { } else {
add(element->getTid()); Add(element.tid());
} }
EntryBaseDropped::add(element); EntryBaseDropped::Add(element);
} }
std::string formatHeader(const std::string& name, log_id_t id) const; std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const;
private:
const pid_t tid_;
pid_t pid_;
uid_t uid_;
char* name_;
}; };
struct TagEntry : public EntryBaseDropped { class TagEntry : public EntryBaseDropped {
const uint32_t tag; public:
pid_t pid; explicit TagEntry(const LogBufferElement& element)
uid_t uid;
explicit TagEntry(const LogBufferElement* element)
: EntryBaseDropped(element), : EntryBaseDropped(element),
tag(element->getTag()), tag_(element.GetTag()),
pid(element->getPid()), pid_(element.pid()),
uid(element->getUid()) { uid_(element.uid()) {}
}
const uint32_t& getKey() const { uint32_t key() const { return tag_; }
return tag; pid_t pid() const { return pid_; }
} uid_t uid() const { return uid_; }
const pid_t& getPid() const { const char* name() const { return android::tagToName(tag_); }
return pid;
}
const uid_t& getUid() const {
return uid;
}
const char* getName() const {
return android::tagToName(tag);
}
inline void add(const LogBufferElement* element) { void Add(const LogBufferElement& element) {
if (uid != element->getUid()) { if (uid_ != element.uid()) {
uid = -1; uid_ = -1;
} }
if (pid != element->getPid()) { if (pid_ != element.pid()) {
pid = -1; pid_ = -1;
} }
EntryBaseDropped::add(element); EntryBaseDropped::Add(element);
} }
std::string formatHeader(const std::string& name, log_id_t id) const; std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const;
private:
const uint32_t tag_;
pid_t pid_;
uid_t uid_;
}; };
struct TagNameKey { struct TagNameKey {
std::string* alloc; std::string* alloc;
std::string_view name; // Saves space if const char* std::string_view name; // Saves space if const char*
explicit TagNameKey(const LogBufferElement* element) explicit TagNameKey(const LogBufferElement& element) : alloc(nullptr), name("", strlen("")) {
: alloc(nullptr), name("", strlen("")) { if (element.IsBinary()) {
if (element->isBinary()) { uint32_t tag = element.GetTag();
uint32_t tag = element->getTag();
if (tag) { if (tag) {
const char* cp = android::tagToName(tag); const char* cp = android::tagToName(tag);
if (cp) { if (cp) {
@ -478,13 +412,13 @@ struct TagNameKey {
name = std::string_view(alloc->c_str(), alloc->size()); name = std::string_view(alloc->c_str(), alloc->size());
return; return;
} }
const char* msg = element->getMsg(); const char* msg = element.msg();
if (!msg) { if (!msg) {
name = std::string_view("chatty", strlen("chatty")); name = std::string_view("chatty", strlen("chatty"));
return; return;
} }
++msg; ++msg;
uint16_t len = element->getMsgLen(); uint16_t len = element.msg_len();
len = (len <= 1) ? 0 : strnlen(msg, len - 1); len = (len <= 1) ? 0 : strnlen(msg, len - 1);
if (!len) { if (!len) {
name = std::string_view("<NULL>", strlen("<NULL>")); name = std::string_view("<NULL>", strlen("<NULL>"));
@ -544,54 +478,43 @@ struct std::hash<TagNameKey>
} }
}; };
struct TagNameEntry : public EntryBase { class TagNameEntry : public EntryBase {
pid_t tid; public:
pid_t pid; explicit TagNameEntry(const LogBufferElement& element)
uid_t uid;
TagNameKey name;
explicit TagNameEntry(const LogBufferElement* element)
: EntryBase(element), : EntryBase(element),
tid(element->getTid()), tid_(element.tid()),
pid(element->getPid()), pid_(element.pid()),
uid(element->getUid()), uid_(element.uid()),
name(element) { name_(element) {}
}
const TagNameKey& getKey() const { const TagNameKey& key() const { return name_; }
return name; pid_t tid() const { return tid_; }
} pid_t pid() const { return pid_; }
const pid_t& getTid() const { uid_t uid() const { return uid_; }
return tid; const char* name() const { return name_.data(); }
} size_t getNameAllocLength() const { return name_.getAllocLength(); }
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) { void Add(const LogBufferElement& element) {
if (uid != element->getUid()) { if (uid_ != element.uid()) {
uid = -1; uid_ = -1;
} }
if (pid != element->getPid()) { if (pid_ != element.pid()) {
pid = -1; pid_ = -1;
} }
if (tid != element->getTid()) { if (tid_ != element.tid()) {
tid = -1; tid_ = -1;
} }
EntryBase::add(element); EntryBase::Add(element);
} }
std::string formatHeader(const std::string& name, log_id_t id) const; std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const;
private:
pid_t tid_;
pid_t pid_;
uid_t uid_;
TagNameKey name_;
}; };
// Log Statistics // Log Statistics
@ -645,11 +568,11 @@ class LogStatistics {
(pidTable.size() * sizeof(pidTable_t::iterator)) + (pidTable.size() * sizeof(pidTable_t::iterator)) +
(tagTable.size() * sizeof(tagTable_t::iterator)); (tagTable.size() * sizeof(tagTable_t::iterator));
for (auto it : pidTable) { for (auto it : pidTable) {
const char* name = it.second.getName(); const char* name = it.second.name();
if (name) size += strlen(name) + 1; if (name) size += strlen(name) + 1;
} }
for (auto it : tidTable) { for (auto it : tidTable) {
const char* name = it.second.getName(); const char* name = it.second.name();
if (name) size += strlen(name) + 1; if (name) size += strlen(name) + 1;
} }
for (auto it : tagNameTable) size += it.second.getNameAllocLength(); for (auto it : tagNameTable) size += it.second.getNameAllocLength();
@ -667,14 +590,14 @@ class LogStatistics {
LogStatistics(bool enable_statistics); LogStatistics(bool enable_statistics);
void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_); void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
void Add(LogBufferElement* entry) EXCLUDES(lock_); void Add(const LogBufferElement& entry) EXCLUDES(lock_);
void Subtract(LogBufferElement* entry) EXCLUDES(lock_); void Subtract(const LogBufferElement& entry) EXCLUDES(lock_);
// entry->setDropped(1) must follow this call // entry->setDropped(1) must follow this call
void Drop(LogBufferElement* entry) EXCLUDES(lock_); void Drop(const LogBufferElement& entry) EXCLUDES(lock_);
// Correct for coalescing two entries referencing dropped content // Correct for coalescing two entries referencing dropped content
void Erase(LogBufferElement* element) EXCLUDES(lock_) { void Erase(const LogBufferElement& element) EXCLUDES(lock_) {
auto lock = std::lock_guard{lock_}; auto lock = std::lock_guard{lock_};
log_id_t log_id = element->getLogId(); log_id_t log_id = element.log_id();
--mElements[log_id]; --mElements[log_id];
--mDroppedElements[log_id]; --mDroppedElements[log_id];
} }

View file

@ -43,9 +43,7 @@ class Prune {
return mPid; return mPid;
} }
int cmp(LogBufferElement* e) const { int cmp(LogBufferElement* e) const { return cmp(e->uid(), e->pid()); }
return cmp(e->getUid(), e->getPid());
}
std::string format(); std::string format();
}; };

View file

@ -44,7 +44,7 @@ std::list<LogBufferElement>::iterator SimpleLogBuffer::GetOldest(log_id_t log_id
if (oldest_[log_id]) { if (oldest_[log_id]) {
it = *oldest_[log_id]; it = *oldest_[log_id];
} }
while (it != logs().end() && it->getLogId() != log_id) { while (it != logs().end() && it->log_id() != log_id) {
it++; it++;
} }
if (it != logs().end()) { if (it != logs().end()) {
@ -102,10 +102,10 @@ int SimpleLogBuffer::Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pi
} }
void SimpleLogBuffer::LogInternal(LogBufferElement&& elem) { void SimpleLogBuffer::LogInternal(LogBufferElement&& elem) {
log_id_t log_id = elem.getLogId(); log_id_t log_id = elem.log_id();
logs_.emplace_back(std::move(elem)); logs_.emplace_back(std::move(elem));
stats_->Add(&logs_.back()); stats_->Add(logs_.back());
MaybePrune(log_id); MaybePrune(log_id);
reader_list_->NotifyNewLog(1 << log_id); reader_list_->NotifyNewLog(1 << log_id);
} }
@ -146,9 +146,9 @@ bool SimpleLogBuffer::FlushTo(
for (it = logs_.end(); it != logs_.begin(); for (it = logs_.end(); it != logs_.begin();
/* do nothing */) { /* do nothing */) {
--it; --it;
if (it->getSequence() == state.start()) { if (it->sequence() == state.start()) {
break; break;
} else if (it->getSequence() < state.start()) { } else if (it->sequence() < state.start()) {
it++; it++;
break; break;
} }
@ -158,19 +158,19 @@ bool SimpleLogBuffer::FlushTo(
for (; it != logs_.end(); ++it) { for (; it != logs_.end(); ++it) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
state.set_start(element.getSequence()); state.set_start(element.sequence());
if (!writer->privileged() && element.getUid() != writer->uid()) { if (!writer->privileged() && element.uid() != writer->uid()) {
continue; continue;
} }
if (((1 << element.getLogId()) & state.log_mask()) == 0) { if (((1 << element.log_id()) & state.log_mask()) == 0) {
continue; continue;
} }
if (filter) { if (filter) {
FilterResult ret = filter(element.getLogId(), element.getPid(), element.getSequence(), FilterResult ret = filter(element.log_id(), element.pid(), element.sequence(),
element.getRealTime(), element.getDropped()); element.realtime(), element.dropped_count());
if (ret == FilterResult::kSkip) { if (ret == FilterResult::kSkip) {
continue; continue;
} }
@ -179,12 +179,12 @@ bool SimpleLogBuffer::FlushTo(
} }
} }
bool same_tid = state.last_tid()[element.getLogId()] == element.getTid(); bool same_tid = state.last_tid()[element.log_id()] == element.tid();
// Dropped (chatty) immediately following a valid log from the same source in the same log // Dropped (chatty) immediately following a valid log from the same source in the same log
// buffer indicates we have a multiple identical squash. chatty that differs source is due // buffer indicates we have a multiple identical squash. chatty that differs source is due
// to spam filter. chatty to chatty of different source is also due to spam filter. // to spam filter. chatty to chatty of different source is also due to spam filter.
state.last_tid()[element.getLogId()] = state.last_tid()[element.log_id()] =
(element.getDropped() && !same_tid) ? 0 : element.getTid(); (element.dropped_count() && !same_tid) ? 0 : element.tid();
shared_lock.unlock(); shared_lock.unlock();
// We never prune logs equal to or newer than any LogReaderThreads' `start` value, so the // We never prune logs equal to or newer than any LogReaderThreads' `start` value, so the
@ -288,22 +288,22 @@ bool SimpleLogBuffer::Prune(log_id_t id, unsigned long prune_rows, uid_t caller_
while (it != logs_.end()) { while (it != logs_.end()) {
LogBufferElement& element = *it; LogBufferElement& element = *it;
if (element.getLogId() != id) { if (element.log_id() != id) {
++it; ++it;
continue; continue;
} }
if (caller_uid != 0 && element.getUid() != caller_uid) { if (caller_uid != 0 && element.uid() != caller_uid) {
++it; ++it;
continue; continue;
} }
if (oldest && oldest->start() <= element.getSequence()) { if (oldest && oldest->start() <= element.sequence()) {
KickReader(oldest, id, prune_rows); KickReader(oldest, id, prune_rows);
return true; return true;
} }
stats_->Subtract(&element); stats_->Subtract(element);
it = Erase(it); it = Erase(it);
if (--prune_rows == 0) { if (--prune_rows == 0) {
return false; return false;