summaryrefslogtreecommitdiffstats
path: root/logd/LogStatistics.cpp
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2015-03-10 13:51:35 -0700
committerMark Salyzyn <salyzyn@google.com>2015-03-20 12:31:23 -0700
commit97c1c2beee2cbd8c67c1cd507367e5b084d853c8 (patch)
tree11842d8e150816d839e355582671dad82278ade5 /logd/LogStatistics.cpp
parentca87790cdccdb0ee17fb4069e6d4ed1e7b4e2ee0 (diff)
downloadcore-97c1c2beee2cbd8c67c1cd507367e5b084d853c8.tar.gz
core-97c1c2beee2cbd8c67c1cd507367e5b084d853c8.tar.bz2
core-97c1c2beee2cbd8c67c1cd507367e5b084d853c8.zip
logd: optimize statistics
- Go back to basic requirements - Simplify - use hash tables to minimize memory impact Bug: 19608965 Change-Id: If7becb34354d6415e5c387ecea7d4109a15259c8
Diffstat (limited to 'logd/LogStatistics.cpp')
-rw-r--r--logd/LogStatistics.cpp864
1 files changed, 164 insertions, 700 deletions
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 5a706899e..19d599c60 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -14,10 +14,12 @@
* limitations under the License.
*/
+#include <algorithm> // std::max
#include <fcntl.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <log/logger.h>
#include <private/android_filesystem_config.h>
@@ -25,80 +27,21 @@
#include "LogStatistics.h"
-PidStatistics::PidStatistics(pid_t pid, char *name)
- : pid(pid)
- , mSizesTotal(0)
- , mElementsTotal(0)
- , mSizes(0)
- , mElements(0)
- , name(name)
- , mGone(false)
-{ }
-
-#ifdef DO_NOT_ERROR_IF_PIDSTATISTICS_USES_A_COPY_CONSTRUCTOR
-PidStatistics::PidStatistics(const PidStatistics &copy)
- : pid(copy->pid)
- , name(copy->name ? strdup(copy->name) : NULL)
- , mSizesTotal(copy->mSizesTotal)
- , mElementsTotal(copy->mElementsTotal)
- , mSizes(copy->mSizes)
- , mElements(copy->mElements)
- , mGone(copy->mGone)
-{ }
-#endif
-
-PidStatistics::~PidStatistics() {
- free(name);
-}
-
-bool PidStatistics::pidGone() {
- if (mGone || (pid == gone)) {
- return true;
- }
- if (pid == 0) {
- return false;
- }
- if (kill(pid, 0) && (errno != EPERM)) {
- mGone = true;
- return true;
- }
- return false;
-}
-
-void PidStatistics::setName(char *new_name) {
- free(name);
- name = new_name;
-}
-
-void PidStatistics::add(unsigned short size) {
- mSizesTotal += size;
- ++mElementsTotal;
- mSizes += size;
- ++mElements;
-}
-
-bool PidStatistics::subtract(unsigned short size) {
- mSizes -= size;
- --mElements;
- return (mElements == 0) && pidGone();
-}
-
-void PidStatistics::addTotal(size_t size, size_t element) {
- if (pid == gone) {
- mSizesTotal += size;
- mElementsTotal += element;
+LogStatistics::LogStatistics() {
+ log_id_for_each(id) {
+ mSizes[id] = 0;
+ mElements[id] = 0;
+ mSizesTotal[id] = 0;
+ mElementsTotal[id] = 0;
}
}
-// must call free to release return value
-// If only we could sniff our own logs for:
-// <time> <pid> <pid> E AndroidRuntime: Process: <name>, PID: <pid>
-// which debuggerd prints as a process is crashing.
-char *PidStatistics::pidToName(pid_t pid) {
+// caller must own and free character string
+char *LogStatistics::pidToName(pid_t pid) {
char *retval = NULL;
if (pid == 0) { // special case from auditd for kernel
retval = strdup("logd.auditd");
- } else if (pid != gone) {
+ } else {
char buffer[512];
snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
int fd = open(buffer, O_RDONLY);
@@ -117,358 +60,105 @@ char *PidStatistics::pidToName(pid_t pid) {
return retval;
}
-UidStatistics::UidStatistics(uid_t uid)
- : uid(uid)
- , mSizes(0)
- , mElements(0) {
- Pids.clear();
-}
-
-UidStatistics::~UidStatistics() {
- PidStatisticsCollection::iterator it;
- for (it = begin(); it != end();) {
- delete (*it);
- it = erase(it);
- }
-}
+void LogStatistics::add(LogBufferElement *e) {
+ log_id_t log_id = e->getLogId();
+ unsigned short size = e->getMsgLen();
+ mSizes[log_id] += size;
+ ++mElements[log_id];
-void UidStatistics::add(unsigned short size, pid_t pid) {
- mSizes += size;
- ++mElements;
-
- PidStatistics *p = NULL;
- PidStatisticsCollection::iterator last;
- PidStatisticsCollection::iterator it;
- for (last = it = begin(); it != end(); last = it, ++it) {
- p = *it;
- if (pid == p->getPid()) {
- p->add(size);
- return;
- }
- }
- // insert if the gone entry.
- bool insert_before_last = (last != it) && p && (p->getPid() == p->gone);
- p = new PidStatistics(pid, pidToName(pid));
- if (insert_before_last) {
- insert(last, p);
+ uid_t uid = e->getUid();
+ android::hash_t hash = android::hash_type(uid);
+ uidTable_t &table = uidTable[log_id];
+ ssize_t index = table.find(-1, hash, uid);
+ if (index == -1) {
+ UidEntry initEntry(uid);
+ initEntry.add(size);
+ table.add(hash, initEntry);
} else {
- push_back(p);
+ UidEntry &entry = table.editEntryAt(index);
+ entry.add(size);
}
- p->add(size);
-}
-
-void UidStatistics::subtract(unsigned short size, pid_t pid) {
- mSizes -= size;
- --mElements;
-
- PidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- PidStatistics *p = *it;
- if (pid == p->getPid()) {
- if (p->subtract(size)) {
- size_t szsTotal = p->sizesTotal();
- size_t elsTotal = p->elementsTotal();
- delete p;
- erase(it);
- it = end();
- --it;
- if (it == end()) {
- p = new PidStatistics(p->gone);
- push_back(p);
- } else {
- p = *it;
- if (p->getPid() != p->gone) {
- p = new PidStatistics(p->gone);
- push_back(p);
- }
- }
- p->addTotal(szsTotal, elsTotal);
- }
- return;
- }
- }
-}
-
-void UidStatistics::sort() {
- for (bool pass = true; pass;) {
- pass = false;
- PidStatisticsCollection::iterator it = begin();
- if (it != end()) {
- PidStatisticsCollection::iterator lt = it;
- PidStatistics *l = (*lt);
- while (++it != end()) {
- PidStatistics *n = (*it);
- if ((n->getPid() != n->gone) && (n->sizes() > l->sizes())) {
- pass = true;
- erase(it);
- insert(lt, n);
- it = lt;
- n = l;
- }
- lt = it;
- l = n;
- }
- }
- }
-}
-size_t UidStatistics::sizes(pid_t pid) {
- if (pid == pid_all) {
- return sizes();
- }
-
- PidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- PidStatistics *p = *it;
- if (pid == p->getPid()) {
- return p->sizes();
- }
- }
- return 0;
+ mSizesTotal[log_id] += size;
+ ++mElementsTotal[log_id];
}
-size_t UidStatistics::elements(pid_t pid) {
- if (pid == pid_all) {
- return elements();
- }
-
- PidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- PidStatistics *p = *it;
- if (pid == p->getPid()) {
- return p->elements();
- }
- }
- return 0;
-}
-
-size_t UidStatistics::sizesTotal(pid_t pid) {
- size_t sizes = 0;
- PidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- PidStatistics *p = *it;
- if ((pid == pid_all) || (pid == p->getPid())) {
- sizes += p->sizesTotal();
- }
- }
- return sizes;
-}
+void LogStatistics::subtract(LogBufferElement *e) {
+ log_id_t log_id = e->getLogId();
+ unsigned short size = e->getMsgLen();
+ mSizes[log_id] -= size;
+ --mElements[log_id];
-size_t UidStatistics::elementsTotal(pid_t pid) {
- size_t elements = 0;
- PidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- PidStatistics *p = *it;
- if ((pid == pid_all) || (pid == p->getPid())) {
- elements += p->elementsTotal();
+ uid_t uid = e->getUid();
+ android::hash_t hash = android::hash_type(uid);
+ uidTable_t &table = uidTable[log_id];
+ ssize_t index = table.find(-1, hash, uid);
+ if (index != -1) {
+ UidEntry &entry = table.editEntryAt(index);
+ if (entry.subtract(size)) {
+ table.removeAt(index);
}
}
- return elements;
-}
-
-LidStatistics::LidStatistics() {
- Uids.clear();
}
-LidStatistics::~LidStatistics() {
- UidStatisticsCollection::iterator it;
- for (it = begin(); it != end();) {
- delete (*it);
- it = Uids.erase(it);
+// caller must own and delete UidEntry array
+const UidEntry **LogStatistics::sort(size_t n, log_id id) {
+ if (!n) {
+ return NULL;
}
-}
-
-void LidStatistics::add(unsigned short size, uid_t uid, pid_t pid) {
- UidStatistics *u;
- UidStatisticsCollection::iterator it;
- UidStatisticsCollection::iterator last;
- if (uid == (uid_t) -1) { // init
- uid = (uid_t) AID_ROOT;
- }
+ const UidEntry **retval = new const UidEntry* [n];
+ memset(retval, 0, sizeof(*retval) * n);
- for (last = it = begin(); it != end(); last = it, ++it) {
- u = *it;
- if (uid == u->getUid()) {
- u->add(size, pid);
- if ((last != it) && ((*last)->sizesTotal() < u->sizesTotal())) {
- Uids.erase(it);
- Uids.insert(last, u);
- }
- return;
- }
- }
- u = new UidStatistics(uid);
- if ((last != it) && ((*last)->sizesTotal() < (size_t) size)) {
- Uids.insert(last, u);
- } else {
- Uids.push_back(u);
- }
- u->add(size, pid);
-}
-
-void LidStatistics::subtract(unsigned short size, uid_t uid, pid_t pid) {
- if (uid == (uid_t) -1) { // init
- uid = (uid_t) AID_ROOT;
- }
-
- UidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- UidStatistics *u = *it;
- if (uid == u->getUid()) {
- u->subtract(size, pid);
- return;
- }
- }
-}
-
-void LidStatistics::sort() {
- for (bool pass = true; pass;) {
- pass = false;
- UidStatisticsCollection::iterator it = begin();
- if (it != end()) {
- UidStatisticsCollection::iterator lt = it;
- UidStatistics *l = (*lt);
- while (++it != end()) {
- UidStatistics *n = (*it);
- if (n->sizes() > l->sizes()) {
- pass = true;
- Uids.erase(it);
- Uids.insert(lt, n);
- it = lt;
- n = l;
- }
- lt = it;
- l = n;
+ uidTable_t &table = uidTable[id];
+ ssize_t index = -1;
+ while ((index = table.next(index)) >= 0) {
+ const UidEntry &entry = table.entryAt(index);
+ size_t s = entry.getSizes();
+ ssize_t i = n - 1;
+ while ((!retval[i] || (s > retval[i]->getSizes())) && (--i >= 0));
+ if (++i < (ssize_t)n) {
+ size_t b = n - i - 1;
+ if (b) {
+ memmove(&retval[i+1], &retval[i], b * sizeof(retval[0]));
}
+ retval[i] = &entry;
}
}
+ return retval;
}
-size_t LidStatistics::sizes(uid_t uid, pid_t pid) {
- size_t sizes = 0;
- UidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- UidStatistics *u = *it;
- if ((uid == uid_all) || (uid == u->getUid())) {
- sizes += u->sizes(pid);
- }
+// caller must own and free character string
+char *LogStatistics::uidToName(uid_t uid) {
+ // Local hard coded favourites
+ if (uid == AID_LOGD) {
+ return strdup("auditd");
}
- return sizes;
-}
-size_t LidStatistics::elements(uid_t uid, pid_t pid) {
- size_t elements = 0;
- UidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- UidStatistics *u = *it;
- if ((uid == uid_all) || (uid == u->getUid())) {
- elements += u->elements(pid);
- }
- }
- return elements;
-}
+ // Android hard coded
+ const struct android_id_info *info = android_ids;
-size_t LidStatistics::sizesTotal(uid_t uid, pid_t pid) {
- size_t sizes = 0;
- UidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- UidStatistics *u = *it;
- if ((uid == uid_all) || (uid == u->getUid())) {
- sizes += u->sizesTotal(pid);
+ for (size_t i = 0; i < android_id_count; ++i) {
+ if (info->aid == uid) {
+ return strdup(info->name);
}
+ ++info;
}
- return sizes;
-}
-
-size_t LidStatistics::elementsTotal(uid_t uid, pid_t pid) {
- size_t elements = 0;
- UidStatisticsCollection::iterator it;
- for (it = begin(); it != end(); ++it) {
- UidStatistics *u = *it;
- if ((uid == uid_all) || (uid == u->getUid())) {
- elements += u->elementsTotal(pid);
- }
- }
- return elements;
-}
-
-LogStatistics::LogStatistics()
- : mStatistics(false)
- , start(CLOCK_MONOTONIC) {
- log_id_for_each(i) {
- mSizes[i] = 0;
- mElements[i] = 0;
- }
-}
-
-void LogStatistics::add(unsigned short size,
- log_id_t log_id, uid_t uid, pid_t pid) {
- mSizes[log_id] += size;
- ++mElements[log_id];
- if (!mStatistics) {
- return;
- }
- id(log_id).add(size, uid, pid);
-}
-
-void LogStatistics::subtract(unsigned short size,
- log_id_t log_id, uid_t uid, pid_t pid) {
- mSizes[log_id] -= size;
- --mElements[log_id];
- if (!mStatistics) {
- return;
- }
- id(log_id).subtract(size, uid, pid);
-}
-
-size_t LogStatistics::sizes(log_id_t log_id, uid_t uid, pid_t pid) {
- if (log_id != log_id_all) {
- return id(log_id).sizes(uid, pid);
- }
- size_t sizes = 0;
- log_id_for_each(i) {
- sizes += id(i).sizes(uid, pid);
- }
- return sizes;
-}
-size_t LogStatistics::elements(log_id_t log_id, uid_t uid, pid_t pid) {
- if (log_id != log_id_all) {
- return id(log_id).elements(uid, pid);
- }
- size_t elements = 0;
- log_id_for_each(i) {
- elements += id(i).elements(uid, pid);
- }
- return elements;
+ // No one
+ return NULL;
}
-size_t LogStatistics::sizesTotal(log_id_t log_id, uid_t uid, pid_t pid) {
- if (log_id != log_id_all) {
- return id(log_id).sizesTotal(uid, pid);
- }
- size_t sizes = 0;
- log_id_for_each(i) {
- sizes += id(i).sizesTotal(uid, pid);
- }
- return sizes;
-}
+static void format_line(android::String8 &output,
+ android::String8 &name, android::String8 &size) {
+ static const size_t total_len = 70;
-size_t LogStatistics::elementsTotal(log_id_t log_id, uid_t uid, pid_t pid) {
- if (log_id != log_id_all) {
- return id(log_id).elementsTotal(uid, pid);
- }
- size_t elements = 0;
- log_id_for_each(i) {
- elements += id(i).elementsTotal(uid, pid);
- }
- return elements;
+ output.appendFormat("%s%*s\n", name.string(),
+ (int)std::max(total_len - name.length() - 1, size.length() + 1)
+ size.string());
}
-void LogStatistics::format(char **buf,
- uid_t uid, unsigned int logMask, log_time oldest) {
- static const unsigned short spaces_current = 13;
+void LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) {
static const unsigned short spaces_total = 19;
if (*buf) {
@@ -476,368 +166,142 @@ void LogStatistics::format(char **buf,
*buf = NULL;
}
- android::String8 string(" span -> size/num");
+ // Report on total logging, current and for all time
+
+ android::String8 output("size/num");
size_t oldLength;
- short spaces = 2;
+ short spaces = 1;
- log_id_for_each(i) {
- if (!(logMask & (1 << i))) {
+ log_id_for_each(id) {
+ if (!(logMask & (1 << id))) {
continue;
}
- oldLength = string.length();
+ oldLength = output.length();
if (spaces < 0) {
spaces = 0;
}
- string.appendFormat("%*s%s", spaces, "", android_log_id_to_name(i));
- spaces += spaces_total + oldLength - string.length();
+ output.appendFormat("%*s%s", spaces, "", android_log_id_to_name(id));
+ spaces += spaces_total + oldLength - output.length();
+ }
- LidStatistics &l = id(i);
- l.sort();
+ spaces = 4;
+ output.appendFormat("\nTotal");
- UidStatisticsCollection::iterator iu;
- for (iu = l.begin(); iu != l.end(); ++iu) {
- (*iu)->sort();
+ log_id_for_each(id) {
+ if (!(logMask & (1 << id))) {
+ continue;
}
- }
-
- spaces = 1;
- log_time t(CLOCK_MONOTONIC);
- unsigned long long d;
- if (mStatistics) {
- d = t.nsec() - start.nsec();
- string.appendFormat("\nTotal%4llu:%02llu:%02llu.%09llu",
- d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
- (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
-
- log_id_for_each(i) {
- if (!(logMask & (1 << i))) {
- continue;
- }
- oldLength = string.length();
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s%zu/%zu", spaces, "",
- sizesTotal(i), elementsTotal(i));
- spaces += spaces_total + oldLength - string.length();
+ oldLength = output.length();
+ if (spaces < 0) {
+ spaces = 0;
}
- spaces = 1;
+ output.appendFormat("%*s%zu/%zu", spaces, "",
+ sizesTotal(id), elementsTotal(id));
+ spaces += spaces_total + oldLength - output.length();
}
- d = t.nsec() - oldest.nsec();
- string.appendFormat("\nNow%6llu:%02llu:%02llu.%09llu",
- d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
- (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
+ spaces = 6;
+ output.appendFormat("\nNow");
- log_id_for_each(i) {
- if (!(logMask & (1 << i))) {
+ log_id_for_each(id) {
+ if (!(logMask & (1 << id))) {
continue;
}
- size_t els = elements(i);
+ size_t els = elements(id);
if (els) {
- oldLength = string.length();
+ oldLength = output.length();
if (spaces < 0) {
spaces = 0;
}
- string.appendFormat("%*s%zu/%zu", spaces, "", sizes(i), els);
- spaces -= string.length() - oldLength;
+ output.appendFormat("%*s%zu/%zu", spaces, "", sizes(id), els);
+ spaces -= output.length() - oldLength;
}
spaces += spaces_total;
}
- // Construct list of worst spammers by Pid
- static const unsigned char num_spammers = 10;
- bool header = false;
+ // Report on Chattiest
- log_id_for_each(i) {
- if (!(logMask & (1 << i))) {
+ // Chattiest by application (UID)
+ log_id_for_each(id) {
+ if (!(logMask & (1 << id))) {
continue;
}
- PidStatisticsCollection pids;
- pids.clear();
-
- LidStatistics &l = id(i);
- UidStatisticsCollection::iterator iu;
- for (iu = l.begin(); iu != l.end(); ++iu) {
- UidStatistics &u = *(*iu);
- PidStatisticsCollection::iterator ip;
- for (ip = u.begin(); ip != u.end(); ++ip) {
- PidStatistics *p = (*ip);
- if (p->getPid() == p->gone) {
- break;
- }
-
- size_t mySizes = p->sizes();
-
- PidStatisticsCollection::iterator q;
- unsigned char num = 0;
- for (q = pids.begin(); q != pids.end(); ++q) {
- if (mySizes > (*q)->sizes()) {
- pids.insert(q, p);
- break;
- }
- // do we need to traverse deeper in the list?
- if (++num > num_spammers) {
- break;
- }
- }
- if (q == pids.end()) {
- pids.push_back(p);
- }
- }
- }
+ static const size_t maximum_sorted_entries = 32;
+ const UidEntry **sorted = sort(maximum_sorted_entries, id);
- size_t threshold = sizes(i);
- if (threshold < 65536) {
- threshold = 65536;
+ if (!sorted) {
+ continue;
}
- threshold /= 100;
-
- PidStatisticsCollection::iterator pt = pids.begin();
- for(int line = 0;
- (pt != pids.end()) && (line < num_spammers);
- ++line, pt = pids.erase(pt)) {
- PidStatistics *p = *pt;
+ bool print = false;
+ for(size_t index = 0; index < maximum_sorted_entries; ++index) {
+ const UidEntry *entry = sorted[index];
- size_t sizes = p->sizes();
- if (sizes < threshold) {
+ if (!entry) {
break;
}
- char *name = p->getName();
- pid_t pid = p->getPid();
- if (!name || !*name) {
- name = pidToName(pid);
- if (name) {
- if (*name) {
- p->setName(name);
- } else {
- free(name);
- name = NULL;
- }
- }
- }
-
- if (!header) {
- string.appendFormat("\n\nChattiest clients:\n"
- "log id %-*s PID[?] name",
- spaces_total, "size/total");
- header = true;
- }
-
- size_t sizesTotal = p->sizesTotal();
-
- android::String8 sz("");
- if (sizes == sizesTotal) {
- sz.appendFormat("%zu", sizes);
- } else {
- sz.appendFormat("%zu/%zu", sizes, sizesTotal);
- }
-
- android::String8 pd("");
- pd.appendFormat("%u%c", pid, p->pidGone() ? '?' : ' ');
-
- string.appendFormat("\n%-7s%-*s %-7s%s",
- line ? "" : android_log_id_to_name(i),
- spaces_total, sz.string(), pd.string(),
- name ? name : "");
- }
-
- pids.clear();
- }
-
- log_id_for_each(i) {
- if (!(logMask & (1 << i))) {
- continue;
- }
-
- header = false;
- bool first = true;
-
- UidStatisticsCollection::iterator ut;
- for(ut = id(i).begin(); ut != id(i).end(); ++ut) {
- UidStatistics *up = *ut;
- if ((uid != AID_ROOT) && (uid != up->getUid())) {
- continue;
+ size_t sizes = entry->getSizes();
+ if (sizes < (65536/100)) {
+ break;
}
- PidStatisticsCollection::iterator pt = up->begin();
- if (pt == up->end()) {
+ uid_t u = entry->getKey();
+ if ((uid != AID_ROOT) && (u != uid)) {
continue;
}
- android::String8 intermediate;
-
- if (!header) {
- // header below tuned to match spaces_total and spaces_current
- spaces = 0;
- intermediate = string.format("%s: UID/PID Total size/num",
- android_log_id_to_name(i));
- string.appendFormat("\n\n%-31sNow "
- "UID/PID[?] Total Now",
- intermediate.string());
- intermediate.clear();
- header = true;
- }
-
- bool oneline = ++pt == up->end();
- --pt;
-
- if (!oneline) {
- first = true;
- } else if (!first && (spaces > 0)) {
- string.appendFormat("%*s", spaces, "");
- }
- spaces = 0;
-
- uid_t u = up->getUid();
- PidStatistics *pp = *pt;
- pid_t p = pp->getPid();
-
- if (!oneline) {
- intermediate = string.format("%d", u);
- } else if (p == PidStatistics::gone) {
- intermediate = string.format("%d/?", u);
- } else if (pp->pidGone()) {
- intermediate = string.format("%d/%d?", u, p);
- } else {
- intermediate = string.format("%d/%d", u, p);
- }
- string.appendFormat(first ? "\n%-12s" : "%-12s",
- intermediate.string());
- intermediate.clear();
-
- size_t elsTotal = up->elementsTotal();
- oldLength = string.length();
- string.appendFormat("%zu/%zu", up->sizesTotal(), elsTotal);
- spaces += spaces_total + oldLength - string.length();
-
- size_t els = up->elements();
- if (els == elsTotal) {
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s=", spaces, "");
- spaces = -1;
- } else if (els) {
- oldLength = string.length();
- if (spaces < 0) {
- spaces = 0;
+ if (!print) {
+ if (uid == AID_ROOT) {
+ output.appendFormat(
+ "\n\nChattiest UIDs in %s:\n",
+ android_log_id_to_name(id));
+ android::String8 name("UID");
+ android::String8 size("Size");
+ format_line(output, name, size);
+ } else {
+ output.appendFormat(
+ "\n\nLogging for your UID in %s:\n",
+ android_log_id_to_name(id));
}
- string.appendFormat("%*s%zu/%zu", spaces, "", up->sizes(), els);
- spaces -= string.length() - oldLength;
+ print = true;
}
- spaces += spaces_current;
-
- first = !first;
- if (oneline) {
- continue;
+ android::String8 name("");
+ name.appendFormat("%u", u);
+ char *n = uidToName(u);
+ if (n) {
+ name.appendFormat("%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n);
+ free(n);
}
- size_t gone_szs = 0;
- size_t gone_els = 0;
-
- for(; pt != up->end(); ++pt) {
- pp = *pt;
- p = pp->getPid();
-
- // If a PID no longer has any current logs, and is not
- // active anymore, skip & report totals for gone.
- elsTotal = pp->elementsTotal();
- size_t szsTotal = pp->sizesTotal();
- if (p == pp->gone) {
- gone_szs += szsTotal;
- gone_els += elsTotal;
- continue;
- }
- els = pp->elements();
- bool gone = pp->pidGone();
- if (gone && (els == 0)) {
- // ToDo: garbage collection: move this statistical bucket
- // from its current UID/PID to UID/? (races and
- // wrap around are our achilles heel). Below is
- // merely lipservice to catch PIDs that were still
- // around when the stats were pruned to zero.
- gone_szs += szsTotal;
- gone_els += elsTotal;
- continue;
- }
-
- if (!first && (spaces > 0)) {
- string.appendFormat("%*s", spaces, "");
- }
- spaces = 0;
-
- intermediate = string.format(gone ? "%d/%d?" : "%d/%d", u, p);
- string.appendFormat(first ? "\n%-12s" : "%-12s",
- intermediate.string());
- intermediate.clear();
-
- oldLength = string.length();
- string.appendFormat("%zu/%zu", szsTotal, elsTotal);
- spaces += spaces_total + oldLength - string.length();
-
- if (els == elsTotal) {
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s=", spaces, "");
- spaces = -1;
- } else if (els) {
- oldLength = string.length();
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s%zu/%zu", spaces, "",
- pp->sizes(), els);
- spaces -= string.length() - oldLength;
- }
- spaces += spaces_current;
+ android::String8 size("");
+ size.appendFormat("%zu", sizes);
- first = !first;
- }
-
- if (gone_els) {
- if (!first && (spaces > 0)) {
- string.appendFormat("%*s", spaces, "");
- }
-
- intermediate = string.format("%d/?", u);
- string.appendFormat(first ? "\n%-12s" : "%-12s",
- intermediate.string());
- intermediate.clear();
-
- spaces = spaces_total + spaces_current;
-
- oldLength = string.length();
- string.appendFormat("%zu/%zu", gone_szs, gone_els);
- spaces -= string.length() - oldLength;
-
- first = !first;
- }
+ format_line(output, name, size);
}
+
+ delete [] sorted;
}
- *buf = strdup(string.string());
+ *buf = strdup(output.string());
}
uid_t LogStatistics::pidToUid(pid_t pid) {
- log_id_for_each(i) {
- LidStatistics &l = id(i);
- UidStatisticsCollection::iterator iu;
- for (iu = l.begin(); iu != l.end(); ++iu) {
- UidStatistics &u = *(*iu);
- PidStatisticsCollection::iterator ip;
- for (ip = u.begin(); ip != u.end(); ++ip) {
- if ((*ip)->getPid() == pid) {
- return u.getUid();
- }
+ char buffer[512];
+ snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
+ FILE *fp = fopen(buffer, "r");
+ if (fp) {
+ while (fgets(buffer, sizeof(buffer), fp)) {
+ int uid;
+ if (sscanf(buffer, "Groups: %d", &uid) == 1) {
+ fclose(fp);
+ return uid;
}
}
+ fclose(fp);
}
return getuid(); // associate this with the logger
}