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 };
static enum match_type Identical(LogBufferElement* elem, LogBufferElement* last) {
// is it mostly identical?
// if (!elem) return DIFFERENT;
ssize_t lenl = elem->getMsgLen();
static enum match_type Identical(const LogBufferElement& elem, const LogBufferElement& last) {
ssize_t lenl = elem.msg_len();
if (lenl <= 0) return DIFFERENT; // value if this represents a chatty elem
// if (!last) return DIFFERENT;
ssize_t lenr = last->getMsgLen();
ssize_t lenr = last.msg_len();
if (lenr <= 0) return DIFFERENT; // value if this represents a chatty elem
// if (elem->getLogId() != last->getLogId()) return DIFFERENT;
if (elem->getUid() != last->getUid()) return DIFFERENT;
if (elem->getPid() != last->getPid()) return DIFFERENT;
if (elem->getTid() != last->getTid()) return DIFFERENT;
if (elem.uid() != last.uid()) return DIFFERENT;
if (elem.pid() != last.pid()) return DIFFERENT;
if (elem.tid() != last.tid()) return DIFFERENT;
// last is more than a minute old, stop squashing identical messages
if (elem->getRealTime().nsec() > (last->getRealTime().nsec() + 60 * NS_PER_SEC))
return DIFFERENT;
if (elem.realtime().nsec() > (last.realtime().nsec() + 60 * NS_PER_SEC)) return DIFFERENT;
// Identical message
const char* msgl = elem->getMsg();
const char* msgr = last->getMsg();
const char* msgl = elem.msg();
const char* msgr = last.msg();
if (lenl == lenr) {
if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME;
// 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)) &&
elem->getTag() == LIBLOG_LOG_TAG) {
elem.GetTag() == LIBLOG_LOG_TAG) {
return SAME_LIBLOG;
}
}
// 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))) {
if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) - sizeof(int32_t))) {
return DIFFERENT;
@ -105,11 +100,11 @@ static enum match_type Identical(LogBufferElement* elem, LogBufferElement* last)
void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
// 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));
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.
if (!last_logged_elements_[log_id]) {
@ -119,12 +114,12 @@ void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
}
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 (duplicate_elements_[log_id]) {
// 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]));
}
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_.
if (match == SAME_LIBLOG) {
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;
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 total = current_last_count + elem_count;
@ -158,22 +153,22 @@ void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
last_logged_elements_[log_id].emplace(std::move(elem));
return;
}
stats()->AddTotal(current_last.getLogId(), current_last.getMsgLen());
stats()->AddTotal(current_last.log_id(), current_last.msg_len());
elem_event->payload.data = total;
last_logged_elements_[log_id].emplace(std::move(elem));
return;
}
// 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()) {
SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id]));
dropped_count = 0;
}
// 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.
current_last.setDropped(dropped_count + 1);
current_last.SetDropped(dropped_count + 1);
duplicate_elements_[log_id].emplace(std::move(current_last));
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,
bool coalesce) {
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
// after the element is erased from the main logging list.
{ // start of scope for found iterator
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.getTag()
: element.getUid();
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.GetTag() : element.uid();
LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
if ((found != mLastWorst[id].end()) && (it == found->second)) {
mLastWorst[id].erase(found);
@ -196,10 +190,10 @@ LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementColl
}
{ // 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
// 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) {
mLastWorstPidOfSystem[id].erase(found);
}
@ -207,14 +201,13 @@ LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementColl
#ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
LogBufferElementCollection::iterator bad = it;
int key =
(id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element->getTag() : element->getUid();
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element->GetTag() : element->uid();
#endif
if (coalesce) {
stats()->Erase(&element);
stats()->Erase(element);
} else {
stats()->Subtract(&element);
stats()->Subtract(element);
}
it = SimpleLogBuffer::Erase(it);
@ -245,15 +238,15 @@ class LogBufferElementLast {
public:
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);
if (it != map.end()) {
LogBufferElement* found = it->second;
uint16_t moreDropped = found->getDropped();
uint16_t moreDropped = found->dropped_count();
if ((dropped + moreDropped) > USHRT_MAX) {
map.erase(it);
} else {
found->setDropped(dropped + moreDropped);
found->SetDropped(dropped + moreDropped);
return true;
}
}
@ -261,18 +254,18 @@ class LogBufferElementLast {
}
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;
}
void clear() { map.clear(); }
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();) {
LogBufferElement* mapElement = it->second;
if (mapElement->getDropped() >= EXPIRE_THRESHOLD &&
current > mapElement->getRealTime().nsec()) {
if (mapElement->dropped_count() >= EXPIRE_THRESHOLD &&
current > mapElement->realtime().nsec()) {
it = map.erase(it);
} else {
++it;
@ -359,12 +352,12 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
while (it != logs().end()) {
LogBufferElement& element = *it;
if (element.getLogId() != id || element.getUid() != caller_uid) {
if (element.log_id() != id || element.uid() != caller_uid) {
++it;
continue;
}
if (oldest && oldest->start() <= element.getSequence()) {
if (oldest && oldest->start() <= element.sequence()) {
busy = true;
KickReader(oldest, id, pruneRows);
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();
while (!clearAll && (pruneRows > 0)) {
// 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 second_worst_sizes = 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()) {
LogBufferElement& element = *it;
if (oldest && oldest->start() <= element.getSequence()) {
if (oldest && oldest->start() <= element.sequence()) {
busy = true;
// Do not let chatty eliding trigger any reader mitigation
break;
}
if (element.getLogId() != id) {
if (element.log_id() != id) {
++it;
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
if (leading && dropped) {
@ -470,8 +463,8 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
continue;
}
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.getTag()
: element.getUid();
int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.GetTag()
: element.uid();
if (hasBlacklist && prune_->naughty(&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) {
break;
}
worst_sizes -= element.getMsgLen();
worst_sizes -= element.msg_len();
}
continue;
}
if (element.getRealTime() < (lastt->getRealTime() - too_old) ||
element.getRealTime() > lastt->getRealTime()) {
if (element.realtime() < (lastt->realtime() - too_old) ||
element.realtime() > lastt->realtime()) {
break;
}
if (dropped) {
last.add(&element);
if (worstPid && ((!gc && element.getPid() == worstPid) ||
mLastWorstPidOfSystem[id].find(element.getPid()) ==
if (worstPid && ((!gc && element.pid() == worstPid) ||
mLastWorstPidOfSystem[id].find(element.pid()) ==
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
// or LOG_ID_SECURITY because of worstPid check.
mLastWorstPidOfSystem[id][element.getPid()] = it;
mLastWorstPidOfSystem[id][element.pid()] = it;
}
if ((!gc && !worstPid && (key == worst)) ||
(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;
}
if (key != worst || (worstPid && element.getPid() != worstPid)) {
if (key != worst || (worstPid && element.pid() != worstPid)) {
leading = false;
last.clear(&element);
++it;
continue;
}
// key == worst below here
// If worstPid set, then element->getPid() == worstPid below here
// If worstPid set, then element->pid() == worstPid below here
pruneRows--;
if (pruneRows == 0) {
@ -534,21 +527,21 @@ bool ChattyLogBuffer::Prune(log_id_t id, unsigned long pruneRows, uid_t caller_u
kick = true;
uint16_t len = element.getMsgLen();
uint16_t len = element.msg_len();
// do not create any leading drops
if (leading) {
it = Erase(it);
} else {
stats()->Drop(&element);
element.setDropped(1);
stats()->Drop(element);
element.SetDropped(1);
if (last.coalesce(&element, 1)) {
it = Erase(it, true);
} else {
last.add(&element);
if (worstPid && (!gc || mLastWorstPidOfSystem[id].find(worstPid) ==
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 or LOG_ID_SECURITY because of worstPid.
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())) {
LogBufferElement& element = *it;
if (element.getLogId() != id) {
if (element.log_id() != id) {
it++;
continue;
}
if (oldest && oldest->start() <= element.getSequence()) {
if (oldest && oldest->start() <= element.sequence()) {
busy = true;
if (!whitelist) KickReader(oldest, id, pruneRows);
break;
}
if (hasWhitelist && !element.getDropped() && prune_->nice(&element)) {
if (hasWhitelist && !element.dropped_count() && prune_->nice(&element)) {
// WhiteListed
whitelist = true;
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)) {
LogBufferElement& element = *it;
if (element.getLogId() != id) {
if (element.log_id() != id) {
++it;
continue;
}
if (oldest && oldest->start() <= element.getSequence()) {
if (oldest && oldest->start() <= element.sequence()) {
busy = true;
KickReader(oldest, id, pruneRows);
break;

View file

@ -32,92 +32,92 @@
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)
: mUid(uid),
mPid(pid),
mTid(tid),
mSequence(sequence),
mRealTime(realtime),
mMsgLen(len),
mLogId(log_id),
mDropped(false) {
mMsg = new char[len];
memcpy(mMsg, msg, len);
: uid_(uid),
pid_(pid),
tid_(tid),
sequence_(sequence),
realtime_(realtime),
msg_len_(len),
log_id_(log_id),
dropped_(false) {
msg_ = new char[len];
memcpy(msg_, msg, len);
}
LogBufferElement::LogBufferElement(const LogBufferElement& elem)
: mUid(elem.mUid),
mPid(elem.mPid),
mTid(elem.mTid),
mSequence(elem.mSequence),
mRealTime(elem.mRealTime),
mMsgLen(elem.mMsgLen),
mLogId(elem.mLogId),
mDropped(elem.mDropped) {
if (mDropped) {
mTag = elem.getTag();
: uid_(elem.uid_),
pid_(elem.pid_),
tid_(elem.tid_),
sequence_(elem.sequence_),
realtime_(elem.realtime_),
msg_len_(elem.msg_len_),
log_id_(elem.log_id_),
dropped_(elem.dropped_) {
if (dropped_) {
tag_ = elem.GetTag();
} else {
mMsg = new char[mMsgLen];
memcpy(mMsg, elem.mMsg, mMsgLen);
msg_ = new char[msg_len_];
memcpy(msg_, elem.msg_, msg_len_);
}
}
LogBufferElement::LogBufferElement(LogBufferElement&& elem)
: mUid(elem.mUid),
mPid(elem.mPid),
mTid(elem.mTid),
mSequence(elem.mSequence),
mRealTime(elem.mRealTime),
mMsgLen(elem.mMsgLen),
mLogId(elem.mLogId),
mDropped(elem.mDropped) {
if (mDropped) {
mTag = elem.getTag();
: uid_(elem.uid_),
pid_(elem.pid_),
tid_(elem.tid_),
sequence_(elem.sequence_),
realtime_(elem.realtime_),
msg_len_(elem.msg_len_),
log_id_(elem.log_id_),
dropped_(elem.dropped_) {
if (dropped_) {
tag_ = elem.GetTag();
} else {
mMsg = elem.mMsg;
elem.mMsg = nullptr;
msg_ = elem.msg_;
elem.msg_ = nullptr;
}
}
LogBufferElement::~LogBufferElement() {
if (!mDropped) {
delete[] mMsg;
if (!dropped_) {
delete[] msg_;
}
}
uint32_t LogBufferElement::getTag() const {
uint32_t LogBufferElement::GetTag() const {
// Binary buffers have no tag.
if (!isBinary()) {
if (!IsBinary()) {
return 0;
}
// Dropped messages store the tag in place of mMsg.
if (mDropped) {
return mTag;
// Dropped messages store the tag in place of msg_.
if (dropped_) {
return tag_;
}
// 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 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) {
if (mDropped) {
return mDroppedCount = value;
uint16_t LogBufferElement::SetDropped(uint16_t value) {
if (dropped_) {
return dropped_count_ = value;
}
// The tag information is saved in mMsg data, which is in a union with mTag, used after mDropped
// is set to true. Therefore we save the tag value aside, delete mMsg, then set mTag to the tag
// 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 msg_, then set tag_ to the tag
// value in its place.
auto old_tag = getTag();
delete[] mMsg;
mMsg = nullptr;
auto old_tag = GetTag();
delete[] msg_;
msg_ = nullptr;
mTag = old_tag;
mDropped = true;
return mDroppedCount = value;
tag_ = old_tag;
dropped_ = true;
return dropped_count_ = value;
}
// caller must own and free character string
@ -165,8 +165,8 @@ char* android::tidToName(pid_t tid) {
return retval;
}
// assumption: mMsg == NULL
size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* stats,
// assumption: msg_ == NULL
size_t LogBufferElement::PopulateDroppedMessage(char*& buffer, LogStatistics* stats,
bool lastSame) {
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";
const char* name = stats->UidToName(mUid);
const char* commName = android::tidToName(mTid);
if (!commName && (mTid != mPid)) {
commName = android::tidToName(mPid);
const char* name = stats->UidToName(uid_);
const char* commName = android::tidToName(tid_);
if (!commName && (tid_ != pid_)) {
commName = android::tidToName(pid_);
}
if (!commName) {
commName = stats->PidToName(mPid);
commName = stats->PidToName(pid_);
}
if (name && name[0] && commName && (name[0] == commName[0])) {
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
const char* type = lastSame ? "identical" : "expire";
size_t len = snprintf(nullptr, 0, format_uid, mUid, name ? name : "",
commName ? commName : "", type, getDropped(),
(getDropped() > 1) ? "s" : "");
size_t len = snprintf(nullptr, 0, format_uid, uid_, name ? name : "", commName ? commName : "",
type, dropped_count(), (dropped_count() > 1) ? "s" : "");
size_t hdrLen;
if (isBinary()) {
if (IsBinary()) {
hdrLen = sizeof(android_log_event_string_t);
} else {
hdrLen = 1 + sizeof(tag);
@ -233,7 +232,7 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* st
}
size_t retval = hdrLen + len;
if (isBinary()) {
if (IsBinary()) {
android_log_event_string_t* event =
reinterpret_cast<android_log_event_string_t*>(buffer);
@ -246,9 +245,8 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* st
strcpy(buffer + 1, tag);
}
snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
commName ? commName : "", type, getDropped(),
(getDropped() > 1) ? "s" : "");
snprintf(buffer + hdrLen, len + 1, format_uid, uid_, name ? name : "", commName ? commName : "",
type, dropped_count(), (dropped_count() > 1) ? "s" : "");
free(const_cast<char*>(name));
free(const_cast<char*>(commName));
@ -259,22 +257,22 @@ bool LogBufferElement::FlushTo(LogWriter* writer, LogStatistics* stats, bool las
struct logger_entry entry = {};
entry.hdr_size = sizeof(struct logger_entry);
entry.lid = mLogId;
entry.pid = mPid;
entry.tid = mTid;
entry.uid = mUid;
entry.sec = mRealTime.tv_sec;
entry.nsec = mRealTime.tv_nsec;
entry.lid = log_id_;
entry.pid = pid_;
entry.tid = tid_;
entry.uid = uid_;
entry.sec = realtime_.tv_sec;
entry.nsec = realtime_.tv_nsec;
char* buffer = nullptr;
const char* msg;
if (mDropped) {
entry.len = populateDroppedMessage(buffer, stats, lastSame);
if (dropped_) {
entry.len = PopulateDroppedMessage(buffer, stats, lastSame);
if (!entry.len) return true;
msg = buffer;
} else {
msg = mMsg;
entry.len = mMsgLen;
msg = msg_;
entry.len = msg_len_;
}
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
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:
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);
@ -60,37 +40,41 @@ class __attribute__((packed)) LogBufferElement {
LogBufferElement(LogBufferElement&& elem);
~LogBufferElement();
bool isBinary(void) const {
return (mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY);
}
bool IsBinary() const { return (log_id_ == LOG_ID_EVENTS) || (log_id_ == LOG_ID_SECURITY); }
log_id_t getLogId() const {
return static_cast<log_id_t>(mLogId);
}
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;
}
uint32_t GetTag() const;
uint16_t SetDropped(uint16_t value);
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];
}
void LogStatistics::Add(LogBufferElement* element) {
void LogStatistics::Add(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_};
log_id_t log_id = element->getLogId();
uint16_t size = element->getMsgLen();
log_id_t log_id = element.log_id();
uint16_t size = element.msg_len();
mSizes[log_id] += size;
++mElements[log_id];
@ -99,7 +99,7 @@ void LogStatistics::Add(LogBufferElement* element) {
// evaluated and trimmed, thus recording size and number of
// elements, but we must recognize the manufactured dropped
// entry as not contributing to the lifetime totals.
if (element->getDropped()) {
if (element.dropped_count()) {
++mDroppedElements[log_id];
} else {
mSizesTotal[log_id] += size;
@ -107,7 +107,7 @@ void LogStatistics::Add(LogBufferElement* element) {
++mElementsTotal[log_id];
}
log_time stamp(element->getRealTime());
log_time stamp(element.realtime());
if (mNewest[log_id] < stamp) {
// A major time update invalidates the statistics :-(
log_time diff = stamp - mNewest[log_id];
@ -132,111 +132,111 @@ void LogStatistics::Add(LogBufferElement* element) {
return;
}
uidTable[log_id].add(element->getUid(), element);
if (element->getUid() == AID_SYSTEM) {
pidSystemTable[log_id].add(element->getPid(), element);
uidTable[log_id].Add(element.uid(), element);
if (element.uid() == AID_SYSTEM) {
pidSystemTable[log_id].Add(element.pid(), element);
}
if (!enable) {
return;
}
pidTable.add(element->getPid(), element);
tidTable.add(element->getTid(), element);
pidTable.Add(element.pid(), element);
tidTable.Add(element.tid(), element);
uint32_t tag = element->getTag();
uint32_t tag = element.GetTag();
if (tag) {
if (log_id == LOG_ID_SECURITY) {
securityTagTable.add(tag, element);
securityTagTable.Add(tag, element);
} else {
tagTable.add(tag, element);
tagTable.Add(tag, element);
}
}
if (!element->getDropped()) {
tagNameTable.add(TagNameKey(element), element);
if (!element.dropped_count()) {
tagNameTable.Add(TagNameKey(element), element);
}
}
void LogStatistics::Subtract(LogBufferElement* element) {
void LogStatistics::Subtract(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_};
log_id_t log_id = element->getLogId();
uint16_t size = element->getMsgLen();
log_id_t log_id = element.log_id();
uint16_t size = element.msg_len();
mSizes[log_id] -= size;
--mElements[log_id];
if (element->getDropped()) {
if (element.dropped_count()) {
--mDroppedElements[log_id];
}
if (mOldest[log_id] < element->getRealTime()) {
mOldest[log_id] = element->getRealTime();
if (mOldest[log_id] < element.realtime()) {
mOldest[log_id] = element.realtime();
}
if (log_id == LOG_ID_KERNEL) {
return;
}
uidTable[log_id].subtract(element->getUid(), element);
if (element->getUid() == AID_SYSTEM) {
pidSystemTable[log_id].subtract(element->getPid(), element);
uidTable[log_id].Subtract(element.uid(), element);
if (element.uid() == AID_SYSTEM) {
pidSystemTable[log_id].Subtract(element.pid(), element);
}
if (!enable) {
return;
}
pidTable.subtract(element->getPid(), element);
tidTable.subtract(element->getTid(), element);
pidTable.Subtract(element.pid(), element);
tidTable.Subtract(element.tid(), element);
uint32_t tag = element->getTag();
uint32_t tag = element.GetTag();
if (tag) {
if (log_id == LOG_ID_SECURITY) {
securityTagTable.subtract(tag, element);
securityTagTable.Subtract(tag, element);
} else {
tagTable.subtract(tag, element);
tagTable.Subtract(tag, element);
}
}
if (!element->getDropped()) {
tagNameTable.subtract(TagNameKey(element), element);
if (!element.dropped_count()) {
tagNameTable.Subtract(TagNameKey(element), element);
}
}
// Atomically set an entry to drop
// 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_};
log_id_t log_id = element->getLogId();
uint16_t size = element->getMsgLen();
log_id_t log_id = element.log_id();
uint16_t size = element.msg_len();
mSizes[log_id] -= size;
++mDroppedElements[log_id];
if (mNewestDropped[log_id] < element->getRealTime()) {
mNewestDropped[log_id] = element->getRealTime();
if (mNewestDropped[log_id] < element.realtime()) {
mNewestDropped[log_id] = element.realtime();
}
uidTable[log_id].drop(element->getUid(), element);
if (element->getUid() == AID_SYSTEM) {
pidSystemTable[log_id].drop(element->getPid(), element);
uidTable[log_id].Drop(element.uid(), element);
if (element.uid() == AID_SYSTEM) {
pidSystemTable[log_id].Drop(element.pid(), element);
}
if (!enable) {
return;
}
pidTable.drop(element->getPid(), element);
tidTable.drop(element->getTid(), element);
pidTable.Drop(element.pid(), element);
tidTable.Drop(element.tid(), element);
uint32_t tag = element->getTag();
uint32_t tag = element.GetTag();
if (tag) {
if (log_id == LOG_ID_SECURITY) {
securityTagTable.drop(tag, element);
securityTagTable.Drop(tag, element);
} 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 {
@ -283,8 +283,8 @@ const char* LogStatistics::UidToNameLocked(uid_t uid) const {
++it) {
const PidEntry& entry = it->second;
if (entry.getUid() == uid) {
const char* nameTmp = entry.getName();
if (entry.uid() == uid) {
const char* nameTmp = entry.name();
if (nameTmp) {
if (!name) {
@ -314,8 +314,8 @@ void LogStatistics::WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& tabl
*worst_sizes = max_entries[0]->getSizes();
// b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
// 100 characters.
if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->getDropped())) {
*worst = max_entries[0]->getKey();
if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->dropped_count())) {
*worst = max_entries[0]->key();
*second_worst_sizes = max_entries[1]->getSizes();
if (*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;
}
*worst = max_entries[0]->getKey();
*worst = max_entries[0]->key();
*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) {
size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
size_t len = EntryBaseConstants::total_len -
EntryBaseConstants::pruned_len - size.length() -
name.length() - lenSpace - 2;
size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
lenSpace - 2;
size_t lenNameTmp = strlen(nameTmp);
while ((len < lenNameTmp) && (lenSpace > 1)) {
++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_) {
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());
stat.FormatTmp(nullptr, uid, name, size, 6);
stat.FormatTmp(nullptr, uid_, name, size, 6);
std::string pruned = "";
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 =
stat.uidTable[id].begin();
it != stat.uidTable[id].end(); ++it) {
totalDropped += it->second.getDropped();
totalDropped += it->second.dropped_count();
}
size_t sizes = stat.mSizes[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();
float virtualEntrySize = entrySize;
int realPermille = virtualEntrySize * 1000.0 / sizes;
size_t dropped = getDropped();
size_t dropped = dropped_count();
if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped);
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(
"%s%d%s", prefix, (permille + 5) / 10, units);
}
ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
pruned.length() - change.length();
ssize_t spaces = EntryBase::PRUNED_LEN - 2 - pruned.length() - change.length();
if ((spaces <= 0) && pruned.length()) {
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);
if (uid != AID_SYSTEM) {
if (uid_ != AID_SYSTEM) {
return output;
}
static const size_t maximum_sorted_entries = 32;
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;
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)) {
break;
}
if (entry->getDropped()) {
if (entry->dropped_count()) {
hasDropped = true;
}
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
REQUIRES(stat.lock_) {
uid_t uid = getUid();
pid_t pid = getPid();
std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
std::string name = android::base::StringPrintf("%5u/%u", pid_, uid_);
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 = "";
size_t dropped = getDropped();
size_t dropped = dropped_count();
if (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
REQUIRES(stat.lock_) {
uid_t uid = getUid();
std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
std::string name = android::base::StringPrintf("%5u/%u", tid(), uid_);
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 = "";
size_t dropped = getDropped();
size_t dropped = dropped_count();
if (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 */,
log_id_t /* id */) const {
std::string name;
uid_t uid = getUid();
if (uid == (uid_t)-1) {
name = android::base::StringPrintf("%7u", getKey());
if (uid_ == (uid_t)-1) {
name = android::base::StringPrintf("%7u", key());
} 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) {
name += android::base::StringPrintf(
"%*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 pruned = "";
size_t dropped = getDropped();
size_t dropped = dropped_count();
if (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 */,
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;
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)) {
if (tid_ == (pid_t)-1 || tid_ == pid_) {
name = android::base::StringPrintf("%*s", len, "");
} else {
name = android::base::StringPrintf("%*u", len, tid);
name = android::base::StringPrintf("%*u", len, tid_);
}
name += pidstr;
uid_t uid = getUid();
if (uid != (uid_t)-1) {
name += android::base::StringPrintf("/%u", uid);
if (uid_ != (uid_t)-1) {
name += android::base::StringPrintf("/%u", uid_);
}
std::string size = android::base::StringPrintf("%zu", getSizes());
const char* nameTmp = getName();
const char* nameTmp = this->name();
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 len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
lenSpace - 2;
size_t lenNameTmp = strlen(nameTmp);
while ((len < lenNameTmp) && (lenSpace > 1)) {
++len;
@ -944,7 +933,7 @@ uid_t pidToUid(pid_t pid) {
uid_t LogStatistics::PidToUid(pid_t pid) {
auto lock = std::lock_guard{lock_};
return pidTable.add(pid)->second.getUid();
return pidTable.Add(pid)->second.uid();
}
// caller must free character string
@ -952,7 +941,7 @@ const char* LogStatistics::PidToName(pid_t pid) const {
auto lock = std::lock_guard{lock_};
// An inconvenient truth ... getName() can alter the object
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) {
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_bucket_overhead = sizeof(void*);
public:
public:
size_t size() const {
return map.size();
}
@ -90,10 +90,10 @@ class LogHashtable {
for (const_iterator it = map.begin(); it != map.end(); ++it) {
const TEntry& entry = it->second;
if ((uid != AID_ROOT) && (uid != entry.getUid())) {
if (uid != AID_ROOT && uid != entry.uid()) {
continue;
}
if (pid && entry.getPid() && (pid != entry.getPid())) {
if (pid && entry.pid() && pid != entry.pid()) {
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);
if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(element))).first;
} else {
it->second.add(element);
it->second.Add(element);
}
return it;
}
inline iterator add(TKey key) {
iterator Add(const TKey& key) {
iterator it = map.find(key);
if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(key))).first;
} else {
it->second.add(key);
it->second.Add(key);
}
return it;
}
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) {
void Subtract(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key);
if ((it != map.end()) && it->second.subtract(element)) {
if (it != map.end() && it->second.Subtract(element)) {
map.erase(it);
}
}
inline void drop(TKey key, const LogBufferElement* element) {
void Drop(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key);
if (it != map.end()) {
it->second.drop(element);
it->second.Drop(element);
}
}
inline iterator begin() {
return map.begin();
}
inline const_iterator begin() const {
return map.begin();
}
inline iterator end() {
return map.end();
}
inline const_iterator end() const {
return map.end();
}
iterator begin() { return map.begin(); }
const_iterator begin() const { return map.begin(); }
iterator end() { return map.end(); }
const_iterator end() const { return map.end(); }
};
namespace EntryBaseConstants {
static constexpr size_t pruned_len = 14;
static constexpr size_t total_len = 80;
}
class EntryBase {
public:
EntryBase() : size_(0) {}
explicit EntryBase(const LogBufferElement& element) : size_(element.msg_len()) {}
struct EntryBase {
size_t size;
size_t getSizes() const { return size_; }
EntryBase() : size(0) {
}
explicit EntryBase(const LogBufferElement* element)
: size(element->getMsgLen()) {
void Add(const LogBufferElement& element) { size_ += element.msg_len(); }
bool Subtract(const LogBufferElement& element) {
size_ -= element.msg_len();
return !size_;
}
size_t getSizes() const {
return size;
}
inline void add(const LogBufferElement* element) {
size += element->getMsgLen();
}
inline bool subtract(const LogBufferElement* element) {
size -= element->getMsgLen();
return !size;
}
static constexpr size_t PRUNED_LEN = 14;
static constexpr size_t TOTAL_LEN = 80;
static std::string formatLine(const std::string& name,
const std::string& size,
const std::string& pruned) {
ssize_t drop_len =
std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
ssize_t size_len =
std::max(size.length() + 1, EntryBaseConstants::total_len -
name.length() - drop_len - 1);
ssize_t drop_len = std::max(pruned.length() + 1, PRUNED_LEN);
ssize_t size_len = std::max(size.length() + 1, TOTAL_LEN - name.length() - drop_len - 1);
std::string ret = android::base::StringPrintf(
"%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);
return ret + "\n";
}
private:
size_t size_;
};
struct EntryBaseDropped : public EntryBase {
size_t dropped;
class EntryBaseDropped : public EntryBase {
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)
: EntryBase(element), dropped(element->getDropped()) {
bool Subtract(const LogBufferElement& element) {
dropped_ -= element.dropped_count();
return EntryBase::Subtract(element) && !dropped_;
}
void Drop(const LogBufferElement& element) {
dropped_ += 1;
EntryBase::Subtract(element);
}
size_t getDropped() const {
return 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);
}
private:
size_t dropped_;
};
struct UidEntry : public EntryBaseDropped {
const uid_t uid;
pid_t pid;
class UidEntry : public EntryBaseDropped {
public:
explicit UidEntry(const LogBufferElement& element)
: EntryBaseDropped(element), uid_(element.uid()), pid_(element.pid()) {}
explicit UidEntry(const LogBufferElement* element)
: EntryBaseDropped(element),
uid(element->getUid()),
pid(element->getPid()) {
}
uid_t key() const { return uid_; }
uid_t uid() const { return key(); }
pid_t pid() const { return pid_; }
inline const uid_t& getKey() const {
return uid;
}
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;
void Add(const LogBufferElement& element) {
if (pid_ != element.pid()) {
pid_ = -1;
}
EntryBaseDropped::add(element);
EntryBaseDropped::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;
private:
const uid_t uid_;
pid_t pid_;
};
namespace android {
uid_t pidToUid(pid_t pid);
}
struct PidEntry : public EntryBaseDropped {
const pid_t pid;
uid_t uid;
char* name;
class PidEntry : public EntryBaseDropped {
public:
explicit PidEntry(pid_t pid)
: EntryBaseDropped(),
pid(pid),
uid(android::pidToUid(pid)),
name(android::pidToName(pid)) {
}
explicit PidEntry(const LogBufferElement* element)
pid_(pid),
uid_(android::pidToUid(pid)),
name_(android::pidToName(pid)) {}
explicit PidEntry(const LogBufferElement& element)
: EntryBaseDropped(element),
pid(element->getPid()),
uid(element->getUid()),
name(android::pidToName(pid)) {
}
pid_(element.pid()),
uid_(element.uid()),
name_(android::pidToName(pid_)) {}
PidEntry(const PidEntry& element)
: EntryBaseDropped(element),
pid(element.pid),
uid(element.uid),
name(element.name ? strdup(element.name) : nullptr) {
}
~PidEntry() {
free(name);
}
pid_(element.pid_),
uid_(element.uid_),
name_(element.name_ ? strdup(element.name_) : nullptr) {}
~PidEntry() { free(name_); }
const pid_t& getKey() const {
return pid;
}
const pid_t& getPid() const {
return getKey();
}
const uid_t& getUid() const {
return uid;
}
const char* getName() const {
return name;
}
pid_t key() const { return pid_; }
pid_t pid() const { return key(); }
uid_t uid() const { return uid_; }
const char* name() const { return name_; }
inline void add(pid_t newPid) {
if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
free(name);
name = nullptr;
void Add(pid_t new_pid) {
if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
free(name_);
name_ = nullptr;
}
if (!name) {
name = android::pidToName(newPid);
if (!name_) {
name_ = android::pidToName(new_pid);
}
}
inline void add(const LogBufferElement* element) {
uid_t incomingUid = element->getUid();
if (getUid() != incomingUid) {
uid = incomingUid;
free(name);
name = android::pidToName(element->getPid());
void Add(const LogBufferElement& element) {
uid_t incoming_uid = element.uid();
if (uid() != incoming_uid) {
uid_ = incoming_uid;
free(name_);
name_ = android::pidToName(element.pid());
} 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 format(const LogStatistics& stat, log_id_t id) const;
private:
const pid_t pid_;
uid_t uid_;
char* name_;
};
struct TidEntry : public EntryBaseDropped {
const pid_t tid;
pid_t pid;
uid_t uid;
char* name;
class TidEntry : public EntryBaseDropped {
public:
TidEntry(pid_t tid, pid_t pid)
: EntryBaseDropped(),
tid(tid),
pid(pid),
uid(android::pidToUid(tid)),
name(android::tidToName(tid)) {
}
explicit TidEntry(const LogBufferElement* element)
tid_(tid),
pid_(pid),
uid_(android::pidToUid(tid)),
name_(android::tidToName(tid)) {}
explicit TidEntry(const LogBufferElement& element)
: EntryBaseDropped(element),
tid(element->getTid()),
pid(element->getPid()),
uid(element->getUid()),
name(android::tidToName(tid)) {
}
tid_(element.tid()),
pid_(element.pid()),
uid_(element.uid()),
name_(android::tidToName(tid_)) {}
TidEntry(const TidEntry& element)
: EntryBaseDropped(element),
tid(element.tid),
pid(element.pid),
uid(element.uid),
name(element.name ? strdup(element.name) : nullptr) {
}
~TidEntry() {
free(name);
}
tid_(element.tid_),
pid_(element.pid_),
uid_(element.uid_),
name_(element.name_ ? strdup(element.name_) : nullptr) {}
~TidEntry() { free(name_); }
const pid_t& getKey() const {
return tid;
}
const pid_t& getTid() const {
return getKey();
}
const pid_t& getPid() const {
return pid;
}
const uid_t& getUid() const {
return uid;
}
const char* getName() const {
return name;
}
pid_t key() const { return tid_; }
pid_t tid() const { return key(); }
pid_t pid() const { return pid_; }
uid_t uid() const { return uid_; }
const char* name() const { return name_; }
inline void add(pid_t incomingTid) {
if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
free(name);
name = nullptr;
void Add(pid_t incomingTid) {
if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
free(name_);
name_ = nullptr;
}
if (!name) {
name = android::tidToName(incomingTid);
if (!name_) {
name_ = android::tidToName(incomingTid);
}
}
inline void add(const LogBufferElement* element) {
uid_t incomingUid = element->getUid();
pid_t incomingPid = element->getPid();
if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
uid = incomingUid;
pid = incomingPid;
free(name);
name = android::tidToName(element->getTid());
void Add(const LogBufferElement& element) {
uid_t incoming_uid = element.uid();
pid_t incoming_pid = element.pid();
if (uid() != incoming_uid || pid() != incoming_pid) {
uid_ = incoming_uid;
pid_ = incoming_pid;
free(name_);
name_ = android::tidToName(element.tid());
} 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 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 {
const uint32_t tag;
pid_t pid;
uid_t uid;
explicit TagEntry(const LogBufferElement* element)
class TagEntry : public EntryBaseDropped {
public:
explicit TagEntry(const LogBufferElement& element)
: EntryBaseDropped(element),
tag(element->getTag()),
pid(element->getPid()),
uid(element->getUid()) {
}
tag_(element.GetTag()),
pid_(element.pid()),
uid_(element.uid()) {}
const uint32_t& getKey() const {
return tag;
}
const pid_t& getPid() const {
return pid;
}
const uid_t& getUid() const {
return uid;
}
const char* getName() const {
return android::tagToName(tag);
}
uint32_t key() const { return tag_; }
pid_t pid() const { return pid_; }
uid_t uid() const { return uid_; }
const char* name() const { return android::tagToName(tag_); }
inline void add(const LogBufferElement* element) {
if (uid != element->getUid()) {
uid = -1;
void Add(const LogBufferElement& element) {
if (uid_ != element.uid()) {
uid_ = -1;
}
if (pid != element->getPid()) {
pid = -1;
if (pid_ != element.pid()) {
pid_ = -1;
}
EntryBaseDropped::add(element);
EntryBaseDropped::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;
private:
const uint32_t tag_;
pid_t pid_;
uid_t uid_;
};
struct TagNameKey {
std::string* alloc;
std::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();
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) {
@ -478,13 +412,13 @@ struct TagNameKey {
name = std::string_view(alloc->c_str(), alloc->size());
return;
}
const char* msg = element->getMsg();
const char* msg = element.msg();
if (!msg) {
name = std::string_view("chatty", strlen("chatty"));
return;
}
++msg;
uint16_t len = element->getMsgLen();
uint16_t len = element.msg_len();
len = (len <= 1) ? 0 : strnlen(msg, len - 1);
if (!len) {
name = std::string_view("<NULL>", strlen("<NULL>"));
@ -544,54 +478,43 @@ struct std::hash<TagNameKey>
}
};
struct TagNameEntry : public EntryBase {
pid_t tid;
pid_t pid;
uid_t uid;
TagNameKey name;
explicit TagNameEntry(const LogBufferElement* element)
class TagNameEntry : public EntryBase {
public:
explicit TagNameEntry(const LogBufferElement& element)
: EntryBase(element),
tid(element->getTid()),
pid(element->getPid()),
uid(element->getUid()),
name(element) {
}
tid_(element.tid()),
pid_(element.pid()),
uid_(element.uid()),
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();
}
const TagNameKey& key() const { return name_; }
pid_t tid() const { return tid_; }
pid_t pid() const { return pid_; }
uid_t uid() const { return uid_; }
const char* name() const { return name_.data(); }
size_t getNameAllocLength() const { return name_.getAllocLength(); }
inline void add(const LogBufferElement* element) {
if (uid != element->getUid()) {
uid = -1;
void Add(const LogBufferElement& element) {
if (uid_ != element.uid()) {
uid_ = -1;
}
if (pid != element->getPid()) {
pid = -1;
if (pid_ != element.pid()) {
pid_ = -1;
}
if (tid != element->getTid()) {
tid = -1;
if (tid_ != element.tid()) {
tid_ = -1;
}
EntryBase::add(element);
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;
private:
pid_t tid_;
pid_t pid_;
uid_t uid_;
TagNameKey name_;
};
// Log Statistics
@ -645,11 +568,11 @@ class LogStatistics {
(pidTable.size() * sizeof(pidTable_t::iterator)) +
(tagTable.size() * sizeof(tagTable_t::iterator));
for (auto it : pidTable) {
const char* name = it.second.getName();
const char* name = it.second.name();
if (name) size += strlen(name) + 1;
}
for (auto it : tidTable) {
const char* name = it.second.getName();
const char* name = it.second.name();
if (name) size += strlen(name) + 1;
}
for (auto it : tagNameTable) size += it.second.getNameAllocLength();
@ -667,14 +590,14 @@ class LogStatistics {
LogStatistics(bool enable_statistics);
void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
void Add(LogBufferElement* entry) EXCLUDES(lock_);
void Subtract(LogBufferElement* entry) EXCLUDES(lock_);
void Add(const LogBufferElement& entry) EXCLUDES(lock_);
void Subtract(const LogBufferElement& entry) EXCLUDES(lock_);
// 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
void Erase(LogBufferElement* element) EXCLUDES(lock_) {
void Erase(const LogBufferElement& element) EXCLUDES(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];
--mDroppedElements[log_id];
}

View file

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

View file

@ -44,7 +44,7 @@ std::list<LogBufferElement>::iterator SimpleLogBuffer::GetOldest(log_id_t log_id
if (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++;
}
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) {
log_id_t log_id = elem.getLogId();
log_id_t log_id = elem.log_id();
logs_.emplace_back(std::move(elem));
stats_->Add(&logs_.back());
stats_->Add(logs_.back());
MaybePrune(log_id);
reader_list_->NotifyNewLog(1 << log_id);
}
@ -146,9 +146,9 @@ bool SimpleLogBuffer::FlushTo(
for (it = logs_.end(); it != logs_.begin();
/* do nothing */) {
--it;
if (it->getSequence() == state.start()) {
if (it->sequence() == state.start()) {
break;
} else if (it->getSequence() < state.start()) {
} else if (it->sequence() < state.start()) {
it++;
break;
}
@ -158,19 +158,19 @@ bool SimpleLogBuffer::FlushTo(
for (; it != logs_.end(); ++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;
}
if (((1 << element.getLogId()) & state.log_mask()) == 0) {
if (((1 << element.log_id()) & state.log_mask()) == 0) {
continue;
}
if (filter) {
FilterResult ret = filter(element.getLogId(), element.getPid(), element.getSequence(),
element.getRealTime(), element.getDropped());
FilterResult ret = filter(element.log_id(), element.pid(), element.sequence(),
element.realtime(), element.dropped_count());
if (ret == FilterResult::kSkip) {
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
// 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.
state.last_tid()[element.getLogId()] =
(element.getDropped() && !same_tid) ? 0 : element.getTid();
state.last_tid()[element.log_id()] =
(element.dropped_count() && !same_tid) ? 0 : element.tid();
shared_lock.unlock();
// 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()) {
LogBufferElement& element = *it;
if (element.getLogId() != id) {
if (element.log_id() != id) {
++it;
continue;
}
if (caller_uid != 0 && element.getUid() != caller_uid) {
if (caller_uid != 0 && element.uid() != caller_uid) {
++it;
continue;
}
if (oldest && oldest->start() <= element.getSequence()) {
if (oldest && oldest->start() <= element.sequence()) {
KickReader(oldest, id, prune_rows);
return true;
}
stats_->Subtract(&element);
stats_->Subtract(element);
it = Erase(it);
if (--prune_rows == 0) {
return false;