LogReader.cpp revision b6bee33182cedea49199eb2252b3f3b442899c6d
10175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn/* 20175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Copyright (C) 2012-2013 The Android Open Source Project 30175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * 40175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 50175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * you may not use this file except in compliance with the License. 60175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * You may obtain a copy of the License at 70175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * 80175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 90175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * 100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Unless required by applicable law or agreed to in writing, software 110175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 120175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * See the License for the specific language governing permissions and 140175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * limitations under the License. 150175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn */ 160175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 17fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#include <ctype.h> 180175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <poll.h> 198daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn#include <sys/prctl.h> 200175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/socket.h> 21dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 220175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <cutils/sockets.h> 230175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "LogReader.h" 250175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "FlushCommand.h" 260175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 277718778793b106498b931dd708a466cf3a6f6a0fMark SalyzynLogReader::LogReader(LogBuffer *logbuf) : 287718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn SocketListener(getLogSocket(), true), 297718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn mLogbuf(*logbuf) { 307718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn} 310175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 320175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// When we are notified a new log entry is available, inform 330175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// all of our listening sockets. 340175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynvoid LogReader::notifyNewLog() { 350175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn FlushCommand command(*this); 360175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn runOnEachSocket(&command); 370175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 380175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 390175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynbool LogReader::onDataAvailable(SocketClient *cli) { 40e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn static bool name_set; 41e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn if (!name_set) { 42e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn prctl(PR_SET_NAME, "logd.reader"); 43e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn name_set = true; 44e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn } 458daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn 460175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn char buffer[255]; 470175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 480175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1); 490175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (len <= 0) { 500175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn doSocketDelete(cli); 510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return false; 520175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 530175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn buffer[len] = '\0'; 540175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 550175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn unsigned long tail = 0; 560175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _tail[] = " tail="; 570175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn char *cp = strstr(buffer, _tail); 580175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 590175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn tail = atol(cp + sizeof(_tail) - 1); 600175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 610175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 62fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn log_time start(log_time::EPOCH); 63fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn static const char _start[] = " start="; 64fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn cp = strstr(buffer, _start); 65fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn if (cp) { 66fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn // Parse errors will result in current time 67fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn start.strptime(cp + sizeof(_start) - 1, "%s.%q"); 68fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn } 69fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn unsigned int logMask = -1; 710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _logIds[] = " lids="; 720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp = strstr(buffer, _logIds); 730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn logMask = 0; 750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp += sizeof(_logIds) - 1; 760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn while (*cp && *cp != '\0') { 770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn int val = 0; 78fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn while (isdigit(*cp)) { 79fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn val = val * 10 + *cp - '0'; 800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn ++cp; 810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn logMask |= 1 << val; 830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (*cp != ',') { 840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn break; 850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn ++cp; 870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 900175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pid_t pid = 0; 910175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _pid[] = " pid="; 920175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp = strstr(buffer, _pid); 930175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 940175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pid = atol(cp + sizeof(_pid) - 1); 950175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 960175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 970175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn bool nonBlock = false; 98ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn if (!fast<strncmp>(buffer, "dumpAndClose", 12)) { 99f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn // Allow writer to get some cycles, and wait for pending notifications 100f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn sched_yield(); 101f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn LogTimeEntry::lock(); 102f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn LogTimeEntry::unlock(); 103f669acb01880216b6c1d29fc226f2c3ec3a6368aMark Salyzyn sched_yield(); 1040175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn nonBlock = true; 1050175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1060175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 107f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn uint64_t sequence = 1; 108f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn // Convert realtime to sequence number 109f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn if (start != log_time::EPOCH) { 110a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn class LogFindStart { 111a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn const pid_t mPid; 112a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn const unsigned mLogMask; 113a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn bool startTimeSet; 114a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time &start; 115f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn uint64_t &sequence; 116f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn uint64_t last; 117b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn bool isMonotonic; 118a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 119a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn public: 120b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence, bool isMonotonic) : 1217718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn mPid(pid), 1227718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn mLogMask(logMask), 1237718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn startTimeSet(false), 1247718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn start(start), 1257718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn sequence(sequence), 126b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn last(sequence), 127b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn isMonotonic(isMonotonic) { 1287718778793b106498b931dd708a466cf3a6f6a0fMark Salyzyn } 129a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 130f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn static int callback(const LogBufferElement *element, void *obj) { 131a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn LogFindStart *me = reinterpret_cast<LogFindStart *>(obj); 132f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn if ((!me->mPid || (me->mPid == element->getPid())) 133a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn && (me->mLogMask & (1 << element->getLogId()))) { 134a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (me->start == element->getRealTime()) { 135f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn me->sequence = element->getSequence(); 136a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->startTimeSet = true; 137f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn return -1; 138b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn } else if (!me->isMonotonic || 139b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn android::isMonotonic(element->getRealTime())) { 140a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (me->start < element->getRealTime()) { 141f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn me->sequence = me->last; 142a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->startTimeSet = true; 143f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn return -1; 144a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 145f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn me->last = element->getSequence(); 146b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn } else { 147b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn me->last = element->getSequence(); 148a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 149a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 150a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn return false; 151a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 152a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 153a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn bool found() { return startTimeSet; } 154b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn } logFindStart(logMask, pid, start, sequence, 155b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn logbuf().isMonotonic() && android::isMonotonic(start)); 156a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 157f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli), 158a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn logFindStart.callback, &logFindStart); 159a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 160a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (!logFindStart.found()) { 161a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (nonBlock) { 162a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn doSocketDelete(cli); 163a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn return false; 164a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 165f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn sequence = LogBufferElement::getCurrentSequence(); 166a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 167fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn } 168fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 169f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence); 1700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn command.runSocketCommand(cli); 1710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return true; 1720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 1730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynvoid LogReader::doSocketDelete(SocketClient *cli) { 1750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes × = mLogbuf.mTimes; 1760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry::lock(); 1770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes::iterator it = times.begin(); 1780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn while(it != times.end()) { 1790175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry *entry = (*it); 1800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (entry->mClient == cli) { 1810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn times.erase(it); 1820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn entry->release_Locked(); 1830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn break; 1840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn it++; 1860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry::unlock(); 1880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 189dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 190dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzynint LogReader::getLogSocket() { 191dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn static const char socketName[] = "logdr"; 192dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn int sock = android_get_control_socket(socketName); 193dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 194dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn if (sock < 0) { 195dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn sock = socket_local_server(socketName, 196dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn ANDROID_SOCKET_NAMESPACE_RESERVED, 197dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn SOCK_SEQPACKET); 198dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn } 199dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 200dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn return sock; 201dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn} 202