logd: Add Pid statistics
- Optional class of statistics for PID
- Enhance pidToName
- Enhanced uidToName
- Enhance pidToUid
- template sort and iteration
Bug: 19608965
Change-Id: I04a1f02e9851b62987f9b176908134e455f22d1d
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index d5b8762..a65ffe0 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -17,6 +17,8 @@
#ifndef _LOGD_LOG_STATISTICS_H__
#define _LOGD_LOG_STATISTICS_H__
+#include <memory>
+#include <stdlib.h>
#include <sys/types.h>
#include <log/log.h>
@@ -27,6 +29,52 @@
#define log_id_for_each(i) \
for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))
+template <typename TKey, typename TEntry>
+class LogHashtable : public android::BasicHashtable<TKey, TEntry> {
+public:
+ std::unique_ptr<const TEntry *[]> sort(size_t n) {
+ if (!n) {
+ std::unique_ptr<const TEntry *[]> sorted(NULL);
+ return sorted;
+ }
+
+ const TEntry **retval = new const TEntry* [n];
+ memset(retval, 0, sizeof(*retval) * n);
+
+ ssize_t index = -1;
+ while ((index = android::BasicHashtable<TKey, TEntry>::next(index)) >= 0) {
+ const TEntry &entry = android::BasicHashtable<TKey, TEntry>::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;
+ }
+ }
+ std::unique_ptr<const TEntry *[]> sorted(retval);
+ return sorted;
+ }
+
+ // Iteration handler for the sort method output
+ static ssize_t next(ssize_t index, std::unique_ptr<const TEntry *[]> &sorted, size_t n) {
+ ++index;
+ if (!sorted.get() || (index < 0) || (n <= (size_t)index) || !sorted[index]
+ || (sorted[index]->getSizes() <= (sorted[0]->getSizes() / 100))) {
+ return -1;
+ }
+ return index;
+ }
+
+ ssize_t next(ssize_t index) {
+ return android::BasicHashtable<TKey, TEntry>::next(index);
+ }
+};
+
struct UidEntry {
const uid_t uid;
size_t size;
@@ -39,27 +87,55 @@
inline bool subtract(size_t s) { size -= s; return !size; }
};
+struct PidEntry {
+ const pid_t pid;
+ uid_t uid;
+ char *name;
+ size_t size;
+
+ PidEntry(pid_t p, uid_t u, char *n):pid(p),uid(u),name(n),size(0) { }
+ PidEntry(const PidEntry &c):
+ pid(c.pid),
+ uid(c.uid),
+ name(c.name ? strdup(c.name) : NULL),
+ size(c.size) { }
+ ~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; }
+ inline void add(size_t s) { size += s; }
+ inline bool subtract(size_t s) { size -= s; return !size; }
+};
+
// Log Statistics
class LogStatistics {
size_t mSizes[LOG_ID_MAX];
size_t mElements[LOG_ID_MAX];
size_t mSizesTotal[LOG_ID_MAX];
size_t mElementsTotal[LOG_ID_MAX];
+ bool enable;
// uid to size list
- typedef android::BasicHashtable<uid_t, UidEntry> uidTable_t;
+ typedef LogHashtable<uid_t, UidEntry> uidTable_t;
uidTable_t uidTable[LOG_ID_MAX];
+ // pid to uid list
+ typedef LogHashtable<pid_t, PidEntry> pidTable_t;
+ pidTable_t pidTable;
+
public:
LogStatistics();
- void enableStatistics() { }
+ void enableStatistics() { enable = true; }
void add(LogBufferElement *entry);
void subtract(LogBufferElement *entry);
- // Caller must delete array
- const UidEntry **sort(size_t n, log_id i);
+ std::unique_ptr<const UidEntry *[]> sort(size_t n, log_id i) { return uidTable[i].sort(n); }
// fast track current value by id only
size_t sizes(log_id_t id) const { return mSizes[id]; }