am dfdff5e4: am cb7f4fd5: am 76ed92c3: Merge "logd: better drop message merging"

* commit 'dfdff5e4800b7d4e931be0eb533a5487aefa5ae7':
  logd: better drop message merging
This commit is contained in:
Mark Salyzyn 2015-04-20 21:54:42 +00:00 committed by Android Git Automerger
commit 50c72e5c6f
1 changed files with 70 additions and 18 deletions

View File

@ -226,6 +226,68 @@ LogBufferElementCollection::iterator LogBuffer::erase(LogBufferElementCollection
return it;
}
// Define a temporary mechanism to report the last LogBufferElement pointer
// for the specified uid, pid and tid. Used below to help merge-sort when
// pruning for worst UID.
class LogBufferElementKey {
const union {
struct {
uint16_t uid;
uint16_t pid;
uint16_t tid;
uint16_t padding;
} __packed;
uint64_t value;
} __packed;
public:
LogBufferElementKey(uid_t u, pid_t p, pid_t t):uid(u),pid(p),tid(t),padding(0) { }
LogBufferElementKey(uint64_t k):value(k) { }
uint64_t getKey() { return value; }
};
struct LogBufferElementEntry {
const uint64_t key;
LogBufferElement *last;
public:
LogBufferElementEntry(const uint64_t &k, LogBufferElement *e):key(k),last(e) { }
const uint64_t&getKey() const { return key; }
LogBufferElement *getLast() { return last; }
};
struct LogBufferElementLast : public android::BasicHashtable<uint64_t, LogBufferElementEntry> {
bool merge(LogBufferElement *e, unsigned short dropped) {
LogBufferElementKey key(e->getUid(), e->getPid(), e->getTid());
android::hash_t hash = android::hash_type(key.getKey());
ssize_t index = find(-1, hash, key.getKey());
if (index != -1) {
LogBufferElementEntry &entry = editEntryAt(index);
LogBufferElement *l = entry.getLast();
unsigned short d = l->getDropped();
if ((dropped + d) > USHRT_MAX) {
removeAt(index);
} else {
l->setDropped(dropped + d);
return true;
}
}
return false;
}
size_t add(LogBufferElement *e) {
LogBufferElementKey key(e->getUid(), e->getPid(), e->getTid());
android::hash_t hash = android::hash_type(key.getKey());
return android::BasicHashtable<uint64_t, LogBufferElementEntry>::
add(hash, LogBufferElementEntry(key.getKey(), e));
}
};
// prune "pruneRows" of type "id" from the buffer.
//
// mLogElementsLock must be held when this function is called.
@ -301,7 +363,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
bool kick = false;
bool leading = true;
LogBufferElement *last = NULL;
LogBufferElementLast last;
for(it = mLogElements.begin(); it != mLogElements.end();) {
LogBufferElement *e = *it;
@ -322,24 +384,18 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
continue;
}
pid_t pid = e->getPid();
// merge any drops
if (last && dropped
&& ((dropped + last->getDropped()) < USHRT_MAX)
&& (last->getPid() == pid)
&& (last->getTid() == e->getTid())) {
if (dropped && last.merge(e, dropped)) {
it = mLogElements.erase(it);
stats.erase(e);
delete e;
last->setDropped(dropped + last->getDropped());
continue;
}
leading = false;
if (hasBlacklist && mPrune.naughty(e)) {
last = NULL;
last.clear();
it = erase(it);
if (dropped) {
continue;
@ -361,13 +417,13 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
}
if (dropped) {
last = e;
last.add(e);
++it;
continue;
}
if (e->getUid() != worst) {
last = NULL;
last.clear();
++it;
continue;
}
@ -382,17 +438,12 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
unsigned short len = e->getMsgLen();
stats.drop(e);
e->setDropped(1);
// merge any drops
if (last
&& (last->getDropped() < (USHRT_MAX - 1))
&& (last->getPid() == pid)
&& (last->getTid() == e->getTid())) {
if (last.merge(e, 1)) {
it = mLogElements.erase(it);
stats.erase(e);
delete e;
last->setDropped(last->getDropped() + 1);
} else {
last = e;
last.add(e);
++it;
}
if (worst_sizes < second_worst_sizes) {
@ -400,6 +451,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
}
worst_sizes -= len;
}
last.clear();
if (!kick || !mPrune.worstUidEnabled()) {
break; // the following loop will ask bad clients to skip/drop