Merge "logd: sum liblog tag messages"
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 3552f70..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,
@@ -222,10 +239,10 @@
// dropped = NULL
// currentLast = copy of last message
// elem = incoming message
- // outgoing: (if *elem == *currentLast)
+ // outgoing: if match != DIFFERENT
// dropped = copy of first identical message -> State 1
// currentLast = reference to elem
- // break: (if *elem != *currentLast)
+ // break: if match == DIFFERENT
// dropped = NULL -> State 0
// delete copy of last message (incoming currentLast)
// currentLast = copy of elem
@@ -237,12 +254,21 @@
// currentLast = reference to last held-back incoming
// message
// elem = incoming message
- // outgoing: (if *elem == *currentLast)
+ // 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
- // break:
+ // 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)
@@ -256,20 +282,54 @@
// message.
// dropped = chatty message holding count
// elem = incoming message
- // outgoing: (if *elem == *currentLast)
+ // 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:
+ // 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
//
- if (identical(elem, currentLast)) {
+ 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;