logd: separate LogStatistics from LogBuffer
LogStatistics is intertwined with LogBuffer, even relying on it for
thread safety. This needs to change to have a proper
LogBufferInterface, so this CL separates them. Specifically:
1) Adding a lock to LogStatistics and adding thread annotations to
ensure that data structures are protected appropriately.
2) Moving prune_rows calculation into LogStatistics so it is done
while holding this lock.
3) Using LogStatistics instead of LogBuffer where appropriate.
Note that there should not be a significant performance regression
with this lock, as it will almost always been uncontended. If
anything, it should alleviate pressure from LogBuffer's lock.
Test: logging unit tests
Change-Id: I9d6dde2c96c9f024fa0341711c7bc63379e8e406
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index ad391e5..4fce751 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -63,8 +63,8 @@
LogReaderThread::unlock();
}
-LogBuffer::LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune)
- : mTimes(*times), tags_(tags), prune_(prune) {
+LogBuffer::LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune, LogStatistics* stats)
+ : mTimes(*times), tags_(tags), prune_(prune), stats_(stats) {
pthread_rwlock_init(&mLogElementsLock, nullptr);
log_id_for_each(i) {
@@ -197,9 +197,7 @@
}
if (!__android_log_is_loggable_len(prio, tag, tag_len, ANDROID_LOG_VERBOSE)) {
// Log traffic received to total
- wrlock();
- stats.addTotal(elem);
- unlock();
+ stats_->AddTotal(elem);
delete elem;
return -EACCES;
}
@@ -308,7 +306,7 @@
unlock();
return len;
}
- stats.addTotal(currentLast);
+ stats_->AddTotal(currentLast);
delete currentLast;
swab = total;
event->payload.data = htole32(swab);
@@ -324,7 +322,7 @@
}
}
if (count) {
- stats.addTotal(currentLast);
+ stats_->AddTotal(currentLast);
currentLast->setDropped(count);
}
droppedElements[log_id] = currentLast;
@@ -355,31 +353,15 @@
// assumes LogBuffer::wrlock() held, owns elem, look after garbage collection
void LogBuffer::log(LogBufferElement* elem) {
mLogElements.push_back(elem);
- stats.add(elem);
+ stats_->Add(elem);
maybePrune(elem->getLogId());
}
-// Prune at most 10% of the log entries or maxPrune, whichever is less.
-//
// LogBuffer::wrlock() must be held when this function is called.
void LogBuffer::maybePrune(log_id_t id) {
- size_t sizes = stats.sizes(id);
- unsigned long maxSize = log_buffer_size(id);
- if (sizes > maxSize) {
- size_t sizeOver = sizes - ((maxSize * 9) / 10);
- size_t elements = stats.realElements(id);
- size_t minElements = elements / 100;
- if (minElements < minPrune) {
- minElements = minPrune;
- }
- unsigned long pruneRows = elements * sizeOver / sizes;
- if (pruneRows < minElements) {
- pruneRows = minElements;
- }
- if (pruneRows > maxPrune) {
- pruneRows = maxPrune;
- }
- prune(id, pruneRows);
+ unsigned long prune_rows;
+ if (stats_->ShouldPrune(id, log_buffer_size(id), &prune_rows)) {
+ prune(id, prune_rows);
}
}
@@ -452,9 +434,9 @@
}
#endif
if (coalesce) {
- stats.erase(element);
+ stats_->Erase(element);
} else {
- stats.subtract(element);
+ stats_->Subtract(element);
}
delete element;
@@ -535,7 +517,7 @@
// If the selected reader is blocking our pruning progress, decide on
// what kind of mitigation is necessary to unblock the situation.
void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows) {
- if (stats.sizes(id) > (2 * log_buffer_size(id))) { // +100%
+ if (stats_->Sizes(id) > (2 * log_buffer_size(id))) { // +100%
// A misbehaving or slow reader has its connection
// dropped if we hit too much memory pressure.
android::prdebug("Kicking blocked reader, pid %d, from LogBuffer::kickMe()\n",
@@ -664,13 +646,13 @@
size_t threshold = log_buffer_size(id) / 8;
if (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) {
- stats.WorstTwoTags(threshold, &worst, &worst_sizes, &second_worst_sizes);
+ stats_->WorstTwoTags(threshold, &worst, &worst_sizes, &second_worst_sizes);
// per-pid filter for AID_SYSTEM sources is too complex
} else {
- stats.WorstTwoUids(id, threshold, &worst, &worst_sizes, &second_worst_sizes);
+ stats_->WorstTwoUids(id, threshold, &worst, &worst_sizes, &second_worst_sizes);
if (worst == AID_SYSTEM && prune_->worstPidOfSystemEnabled()) {
- stats.WorstTwoSystemPids(id, worst_sizes, &worstPid, &second_worst_sizes);
+ stats_->WorstTwoSystemPids(id, worst_sizes, &worstPid, &second_worst_sizes);
}
}
}
@@ -819,7 +801,7 @@
if (leading) {
it = erase(it);
} else {
- stats.drop(element);
+ stats_->Drop(element);
element->setDropped(1);
if (last.coalesce(element, 1)) {
it = erase(it, true);
@@ -952,14 +934,6 @@
return busy;
}
-// get the used space associated with "id".
-unsigned long LogBuffer::getSizeUsed(log_id_t id) {
- rdlock();
- size_t retval = stats.sizes(id);
- unlock();
- return retval;
-}
-
// set the total space allocated to "id"
int LogBuffer::setSize(log_id_t id, unsigned long size) {
// Reasonable limits ...
@@ -1044,7 +1018,7 @@
unlock();
// range locking in LastLogTimes looks after us
- curr = element->flushTo(reader, this, sameTid);
+ curr = element->flushTo(reader, stats_, sameTid);
if (curr == element->FLUSH_ERROR) {
return curr;
@@ -1056,14 +1030,3 @@
return curr;
}
-
-std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
- unsigned int logMask) {
- wrlock();
-
- std::string ret = stats.format(uid, pid, logMask);
-
- unlock();
-
- return ret;
-}