logd: class hierarcy for Uid and Pid statistics.

Add EntryBase and EntryBaseDropped base classes for statistical
entries to inherit from. Abstract add(), subtract() and drop()
methods to common LogBufferElement in each for entry policy decisions.
Some move of details out of LogStatistics.cpp and place them into
LogStatistics.h. Add statistical add(), subtract() and
drop() methods to hash table to call entries for policy.

Bug: 19608965
Change-Id: Ib8a33a8fe28871ef165d1632c6546a5c606231e8
This commit is contained in:
Mark Salyzyn 2015-04-13 14:24:45 -07:00
parent 5720d2c168
commit 81b3eabc49
3 changed files with 127 additions and 138 deletions

View File

@ -25,6 +25,9 @@
#include <log/log.h>
#include <log/log_read.h>
// Hijack this header as a common include file used by most all sources
// to report some utilities defined here and there.
namespace android {
// Furnished in main.cpp. Caller must own and free returned value

View File

@ -39,7 +39,7 @@ LogStatistics::LogStatistics()
namespace android {
// caller must own and free character string
static char *pidToName(pid_t pid) {
char *pidToName(pid_t pid) {
char *retval = NULL;
if (pid == 0) { // special case from auditd for kernel
retval = strdup("logd.auditd");
@ -70,21 +70,7 @@ void LogStatistics::add(LogBufferElement *e) {
mSizes[log_id] += size;
++mElements[log_id];
uid_t uid = e->getUid();
unsigned short dropped = e->getDropped();
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);
initEntry.add_dropped(dropped);
table.add(hash, initEntry);
} else {
UidEntry &entry = table.editEntryAt(index);
entry.add(size);
entry.add_dropped(dropped);
}
uidTable[log_id].add(e->getUid(), e);
mSizesTotal[log_id] += size;
++mElementsTotal[log_id];
@ -93,28 +79,7 @@ void LogStatistics::add(LogBufferElement *e) {
return;
}
pid_t pid = e->getPid();
hash = android::hash_type(pid);
index = pidTable.find(-1, hash, pid);
if (index == -1) {
PidEntry initEntry(pid, uid, android::pidToName(pid));
initEntry.add(size);
initEntry.add_dropped(dropped);
pidTable.add(hash, initEntry);
} else {
PidEntry &entry = pidTable.editEntryAt(index);
if (entry.getUid() != uid) {
entry.setUid(uid);
entry.setName(android::pidToName(pid));
} else if (!entry.getName()) {
char *name = android::pidToName(pid);
if (name) {
entry.setName(name);
}
}
entry.add(size);
entry.add_dropped(dropped);
}
pidTable.add(e->getPid(), e);
}
void LogStatistics::subtract(LogBufferElement *e) {
@ -123,31 +88,13 @@ void LogStatistics::subtract(LogBufferElement *e) {
mSizes[log_id] -= size;
--mElements[log_id];
uid_t uid = e->getUid();
unsigned short dropped = e->getDropped();
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) || entry.subtract_dropped(dropped)) {
table.removeAt(index);
}
}
uidTable[log_id].subtract(e->getUid(), e);
if (!enable) {
return;
}
pid_t pid = e->getPid();
hash = android::hash_type(pid);
index = pidTable.find(-1, hash, pid);
if (index != -1) {
PidEntry &entry = pidTable.editEntryAt(index);
if (entry.subtract(size) || entry.subtract_dropped(dropped)) {
pidTable.removeAt(index);
}
}
pidTable.subtract(e->getPid(), e);
}
// Atomically set an entry to drop
@ -157,28 +104,13 @@ void LogStatistics::drop(LogBufferElement *e) {
unsigned short size = e->getMsgLen();
mSizes[log_id] -= size;
uid_t uid = e->getUid();
android::hash_t hash = android::hash_type(uid);
typeof uidTable[0] &table = uidTable[log_id];
ssize_t index = table.find(-1, hash, uid);
if (index != -1) {
UidEntry &entry = table.editEntryAt(index);
entry.subtract(size);
entry.add_dropped(1);
}
uidTable[log_id].drop(e->getUid(), e);
if (!enable) {
return;
}
pid_t pid = e->getPid();
hash = android::hash_type(pid);
index = pidTable.find(-1, hash, pid);
if (index != -1) {
PidEntry &entry = pidTable.editEntryAt(index);
entry.subtract(size);
entry.add_dropped(1);
}
pidTable.drop(e->getPid(), e);
}
// caller must own and free character string
@ -379,6 +311,7 @@ void LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) {
}
if (enable) {
// Pid table
bool headerPrinted = false;
std::unique_ptr<const PidEntry *[]> sorted = pidTable.sort(maximum_sorted_entries);
ssize_t index = -1;
@ -460,48 +393,14 @@ uid_t pidToUid(pid_t pid) {
}
uid_t LogStatistics::pidToUid(pid_t pid) {
uid_t uid;
android::hash_t hash = android::hash_type(pid);
ssize_t index = pidTable.find(-1, hash, pid);
if (index == -1) {
uid = android::pidToUid(pid);
PidEntry initEntry(pid, uid, android::pidToName(pid));
pidTable.add(hash, initEntry);
} else {
PidEntry &entry = pidTable.editEntryAt(index);
if (!entry.getName()) {
char *name = android::pidToName(pid);
if (name) {
entry.setName(name);
}
}
uid = entry.getUid();
}
return uid;
return pidTable.entryAt(pidTable.add(pid)).getUid();
}
// caller must free character string
char *LogStatistics::pidToName(pid_t pid) {
char *name;
android::hash_t hash = android::hash_type(pid);
ssize_t index = pidTable.find(-1, hash, pid);
if (index == -1) {
name = android::pidToName(pid);
PidEntry initEntry(pid, android::pidToUid(pid), name ? strdup(name) : NULL);
pidTable.add(hash, initEntry);
} else {
PidEntry &entry = pidTable.editEntryAt(index);
const char *n = entry.getName();
if (n) {
name = strdup(n);
} else {
name = android::pidToName(pid);
if (name) {
entry.setName(strdup(name));
}
}
const char *name = pidTable.entryAt(pidTable.add(pid)).getName();
if (!name) {
return NULL;
}
return name;
return strdup(name);
}

View File

@ -73,52 +73,139 @@ public:
ssize_t next(ssize_t index) {
return android::BasicHashtable<TKey, TEntry>::next(index);
}
size_t add(TKey key, LogBufferElement *e) {
android::hash_t hash = android::hash_type(key);
ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, hash, key);
if (index == -1) {
return android::BasicHashtable<TKey, TEntry>::add(hash, TEntry(e));
}
android::BasicHashtable<TKey, TEntry>::editEntryAt(index).add(e);
return index;
}
inline size_t add(TKey key) {
android::hash_t hash = android::hash_type(key);
ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, hash, key);
if (index == -1) {
return android::BasicHashtable<TKey, TEntry>::add(hash, TEntry(key));
}
android::BasicHashtable<TKey, TEntry>::editEntryAt(index).add(key);
return index;
}
void subtract(TKey key, LogBufferElement *e) {
ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, android::hash_type(key), key);
if ((index != -1)
&& android::BasicHashtable<TKey, TEntry>::editEntryAt(index).subtract(e)) {
android::BasicHashtable<TKey, TEntry>::removeAt(index);
}
}
inline void drop(TKey key, LogBufferElement *e) {
ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, android::hash_type(key), key);
if (index != -1) {
android::BasicHashtable<TKey, TEntry>::editEntryAt(index).drop(e);
}
}
};
struct UidEntry {
const uid_t uid;
struct EntryBase {
size_t size;
EntryBase():size(0) { }
EntryBase(LogBufferElement *e):size(e->getMsgLen()) { }
size_t getSizes() const { return size; }
inline void add(LogBufferElement *e) { size += e->getMsgLen(); }
inline bool subtract(LogBufferElement *e) { size -= e->getMsgLen(); return !size; }
};
struct EntryBaseDropped : public EntryBase {
size_t dropped;
UidEntry(uid_t uid):uid(uid),size(0),dropped(0) { }
EntryBaseDropped():dropped(0) { }
EntryBaseDropped(LogBufferElement *e):EntryBase(e),dropped(e->getDropped()){ }
inline const uid_t&getKey() const { return uid; }
size_t getSizes() const { return size; }
size_t getDropped() const { return dropped; }
inline void add(size_t s) { size += s; }
inline void add_dropped(size_t d) { dropped += d; }
inline bool subtract(size_t s) { size -= s; return !dropped && !size; }
inline bool subtract_dropped(size_t d) { dropped -= d; return !dropped && !size; }
inline void add(LogBufferElement *e) {
dropped += e->getDropped();
EntryBase::add(e);
}
inline bool subtract(LogBufferElement *e) {
dropped -= e->getDropped();
return EntryBase::subtract(e) && !dropped;
}
inline void drop(LogBufferElement *e) {
dropped += 1;
EntryBase::subtract(e);
}
};
struct PidEntry {
struct UidEntry : public EntryBaseDropped {
const uid_t uid;
UidEntry(LogBufferElement *e):EntryBaseDropped(e),uid(e->getUid()) { }
inline const uid_t&getKey() const { return uid; }
};
namespace android {
// caller must own and free character string
char *pidToName(pid_t pid);
uid_t pidToUid(pid_t pid);
}
struct PidEntry : public EntryBaseDropped {
const pid_t pid;
uid_t uid;
char *name;
size_t size;
size_t dropped;
PidEntry(pid_t p, uid_t u, char *n):pid(p),uid(u),name(n),size(0),dropped(0) { }
PidEntry(pid_t p):
EntryBaseDropped(),
pid(p),
uid(android::pidToUid(p)),
name(android::pidToName(pid)) { }
PidEntry(LogBufferElement *e):
EntryBaseDropped(e),
pid(e->getPid()),
uid(e->getUid()),
name(android::pidToName(e->getPid())) { }
PidEntry(const PidEntry &c):
EntryBaseDropped(c),
pid(c.pid),
uid(c.uid),
name(c.name ? strdup(c.name) : NULL),
size(c.size),
dropped(c.dropped) { }
name(c.name ? strdup(c.name) : NULL) { }
~PidEntry() { free(name); }
const pid_t&getKey() const { return pid; }
const uid_t&getUid() const { return uid; }
uid_t&setUid(uid_t u) { return uid = u; }
const char*getName() const { return name; }
char *setName(char *n) { free(name); return name = n; }
size_t getSizes() const { return size; }
size_t getDropped() const { return dropped; }
inline void add(size_t s) { size += s; }
inline void add_dropped(size_t d) { dropped += d; }
inline bool subtract(size_t s) { size -= s; return !dropped && !size; }
inline bool subtract_dropped(size_t d) { dropped -= d; return !dropped && !size; }
inline void add(pid_t p) {
if (!name) {
char *n = android::pidToName(p);
if (n) {
name = n;
}
}
}
inline void add(LogBufferElement *e) {
uid_t u = e->getUid();
if (getUid() != u) {
uid = u;
free(name);
name = android::pidToName(e->getPid());
} else {
add(e->getPid());
}
EntryBaseDropped::add(e);
}
};
// Log Statistics