Merge "logd: trailing spaces in log statistics (part deux)"
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 6e6d69f..ba44a5a 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -464,7 +464,7 @@
if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) {
errno = EINVAL;
if (end_idx) *end_idx = start_idx;
- if (attempted_idx) *end_idx = start_idx;
+ if (attempted_idx) *attempted_idx = start_idx;
return -1;
}
diff --git a/logd/Android.mk b/logd/Android.mk
index 7fe48d7..2da9782 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -40,6 +40,7 @@
# event_flag += $(call event_logtags,logd)
# so make sure we do not regret hard-coding it as follows:
event_flag := -DAUDITD_LOG_TAG=1003 -DCHATTY_LOG_TAG=1004
+event_flag += -DLIBLOG_LOG_TAG=1006
LOCAL_CFLAGS := -Werror $(event_flag)
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index d476596..a5d435f 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -17,6 +17,7 @@
//#define DEBUG_CHECK_FOR_STALE_ENTRIES
#include <ctype.h>
+#include <endian.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -126,27 +127,41 @@
}
}
-static bool identical(LogBufferElement* elem, LogBufferElement* last) {
+enum match_type {
+ DIFFERENT,
+ SAME,
+ SAME_LIBLOG
+};
+
+static enum match_type identical(LogBufferElement* elem, LogBufferElement* last) {
// is it mostly identical?
-// if (!elem) return false;
+// if (!elem) return DIFFERENT;
unsigned short lenl = elem->getMsgLen();
- if (!lenl) return false;
-// if (!last) return false;
+ if (!lenl) return DIFFERENT;
+// if (!last) return DIFFERENT;
unsigned short lenr = last->getMsgLen();
- if (!lenr) return false;
-// if (elem->getLogId() != last->getLogId()) return false;
- if (elem->getUid() != last->getUid()) return false;
- if (elem->getPid() != last->getPid()) return false;
- if (elem->getTid() != last->getTid()) return false;
+ if (!lenr) return DIFFERENT;
+// if (elem->getLogId() != last->getLogId()) return DIFFERENT;
+ if (elem->getUid() != last->getUid()) return DIFFERENT;
+ if (elem->getPid() != last->getPid()) return DIFFERENT;
+ if (elem->getTid() != last->getTid()) return DIFFERENT;
// last is more than a minute old, stop squashing identical messages
if (elem->getRealTime().nsec() >
- (last->getRealTime().nsec() + 60 * NS_PER_SEC)) return false;
+ (last->getRealTime().nsec() + 60 * NS_PER_SEC)) return DIFFERENT;
// Identical message
const char* msgl = elem->getMsg();
const char* msgr = last->getMsg();
- if ((lenl == lenr) && !fastcmp<memcmp>(msgl, msgr, lenl)) return true;
+ if (lenl == lenr) {
+ if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME;
+ // liblog tagged messages (content gets summed)
+ if ((elem->getLogId() == LOG_ID_EVENTS) &&
+ (lenl == sizeof(android_log_event_int_t)) &&
+ !fastcmp<memcmp>(msgl, msgr,
+ sizeof(android_log_event_int_t) - sizeof(int32_t)) &&
+ (elem->getTag() == LIBLOG_LOG_TAG)) return SAME_LIBLOG;
+ }
// audit message (except sequence number) identical?
static const char avc[] = "): avc: ";
@@ -154,20 +169,22 @@
if (last->isBinary()) {
if (fastcmp<memcmp>(msgl, msgr,
sizeof(android_log_event_string_t) -
- sizeof(int32_t))) return false;
+ sizeof(int32_t))) return DIFFERENT;
msgl += sizeof(android_log_event_string_t);
lenl -= sizeof(android_log_event_string_t);
msgr += sizeof(android_log_event_string_t);
lenr -= sizeof(android_log_event_string_t);
}
const char *avcl = android::strnstr(msgl, lenl, avc);
- if (!avcl) return false;
+ if (!avcl) return DIFFERENT;
lenl -= avcl - msgl;
const char *avcr = android::strnstr(msgr, lenr, avc);
- if (!avcr) return false;
+ if (!avcr) return DIFFERENT;
lenr -= avcr - msgr;
- if (lenl != lenr) return false;
- return !fastcmp<memcmp>(avcl + strlen(avc), avcr + strlen(avc), lenl);
+ if (lenl != lenr) return DIFFERENT;
+ if (fastcmp<memcmp>(avcl + strlen(avc),
+ avcr + strlen(avc), lenl)) return DIFFERENT;
+ return SAME;
}
int LogBuffer::log(log_id_t log_id, log_time realtime,
@@ -206,8 +223,113 @@
if (currentLast) {
LogBufferElement *dropped = droppedElements[log_id];
unsigned short count = dropped ? dropped->getDropped() : 0;
- if (identical(elem, currentLast)) {
+ //
+ // State Init
+ // incoming:
+ // dropped = NULL
+ // currentLast = NULL;
+ // elem = incoming message
+ // outgoing:
+ // dropped = NULL -> State 0
+ // currentLast = copy of elem
+ // log elem
+ // State 0
+ // incoming:
+ // count = 0
+ // dropped = NULL
+ // currentLast = copy of last message
+ // elem = incoming message
+ // outgoing: if match != DIFFERENT
+ // dropped = copy of first identical message -> State 1
+ // currentLast = reference to elem
+ // break: if match == DIFFERENT
+ // dropped = NULL -> State 0
+ // delete copy of last message (incoming currentLast)
+ // currentLast = copy of elem
+ // log elem
+ // State 1
+ // incoming:
+ // count = 0
+ // dropped = copy of first identical message
+ // currentLast = reference to last held-back incoming
+ // message
+ // elem = incoming message
+ // outgoing: if match == SAME
+ // delete copy of first identical message (dropped)
+ // dropped = reference to last held-back incoming
+ // message set to chatty count of 1 -> State 2
+ // currentLast = reference to elem
+ // outgoing: if match == SAME_LIBLOG
+ // dropped = copy of first identical message -> State 1
+ // take sum of currentLast and elem
+ // if sum overflows:
+ // log currentLast
+ // currentLast = reference to elem
+ // else
+ // delete currentLast
+ // currentLast = reference to elem, sum liblog.
+ // break: if match == DIFFERENT
+ // delete dropped
+ // dropped = NULL -> State 0
+ // log reference to last held-back (currentLast)
+ // currentLast = copy of elem
+ // log elem
+ // State 2
+ // incoming:
+ // count = chatty count
+ // dropped = chatty message holding count
+ // currentLast = reference to last held-back incoming
+ // message.
+ // dropped = chatty message holding count
+ // elem = incoming message
+ // outgoing: if match != DIFFERENT
+ // delete chatty message holding count
+ // dropped = reference to last held-back incoming
+ // message, set to chatty count + 1
+ // currentLast = reference to elem
+ // break: if match == DIFFERENT
+ // log dropped (chatty message)
+ // dropped = NULL -> State 0
+ // log reference to last held-back (currentLast)
+ // currentLast = copy of elem
+ // log elem
+ //
+ enum match_type match = identical(elem, currentLast);
+ if (match != DIFFERENT) {
if (dropped) {
+ // Sum up liblog tag messages?
+ if ((count == 0) /* at Pass 1 */ && (match == SAME_LIBLOG)) {
+ android_log_event_int_t* event =
+ reinterpret_cast<android_log_event_int_t*>(
+ const_cast<char*>(currentLast->getMsg()));
+ //
+ // To unit test, differentiate with something like:
+ // event->header.tag = htole32(CHATTY_LOG_TAG);
+ // here, then instead of delete currentLast below,
+ // log(currentLast) to see the incremental sums form.
+ //
+ uint32_t swab = event->payload.data;
+ unsigned long long total = htole32(swab);
+ event = reinterpret_cast<android_log_event_int_t*>(
+ const_cast<char*>(elem->getMsg()));
+ swab = event->payload.data;
+
+ lastLoggedElements[LOG_ID_EVENTS] = elem;
+ total += htole32(swab);
+ // check for overflow
+ if (total >= UINT32_MAX) {
+ log(currentLast);
+ pthread_mutex_unlock(&mLogElementsLock);
+ return len;
+ }
+ stats.add(currentLast);
+ stats.subtract(currentLast);
+ delete currentLast;
+ swab = total;
+ event->payload.data = htole32(swab);
+ pthread_mutex_unlock(&mLogElementsLock);
+ return len;
+ }
if (count == USHRT_MAX) {
log(dropped);
count = 1;
@@ -226,13 +348,15 @@
pthread_mutex_unlock(&mLogElementsLock);
return len;
}
- if (dropped) {
- log(dropped);
+ if (dropped) { // State 1 or 2
+ if (count) { // State 2
+ log(dropped); // report chatty
+ } else { // State 1
+ delete dropped;
+ }
droppedElements[log_id] = NULL;
- }
- if (count) {
- log(currentLast);
- } else {
+ log(currentLast); // report last message in the series
+ } else { // State 0
delete currentLast;
}
}
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 31de2a0..273150e 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -27,6 +27,8 @@
#include "LogStatistics.h"
+size_t LogStatistics::SizesTotal;
+
LogStatistics::LogStatistics() : enable(false) {
log_id_for_each(id) {
mSizes[id] = 0;
@@ -39,6 +41,8 @@
namespace android {
+size_t sizesTotal() { return LogStatistics::sizesTotal(); }
+
// caller must own and free character string
char *pidToName(pid_t pid) {
char *retval = NULL;
@@ -80,6 +84,7 @@
// elements, but we must recognize the manufactured dropped
// entry as not contributing to the lifetime totals.
mSizesTotal[log_id] += size;
+ SizesTotal += size;
++mElementsTotal[log_id];
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 1d687bc..7acef6d 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -475,6 +475,7 @@
size_t mDroppedElements[LOG_ID_MAX];
size_t mSizesTotal[LOG_ID_MAX];
size_t mElementsTotal[LOG_ID_MAX];
+ static size_t SizesTotal;
bool enable;
// uid to size list
@@ -557,6 +558,7 @@
}
size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
+ static size_t sizesTotal() { return SizesTotal; }
std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index d300a2a..70f24e4 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -33,7 +33,9 @@
char *uidToName(uid_t uid);
void prdebug(const char *fmt, ...) __printflike(1, 2);
-// Furnished in LogStatistics.cpp. Caller must own and free returned value
+// Furnished in LogStatistics.cpp.
+size_t sizesTotal();
+// Caller must own and free returned value
char *pidToName(pid_t pid);
char *tidToName(pid_t tid);