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 270175b0747a1f55329109e84c9a1322dcb95e2848Mark SalyzynLogReader::LogReader(LogBuffer *logbuf) 28dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn : SocketListener(getLogSocket(), true) 290175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn , mLogbuf(*logbuf) 300175b0747a1f55329109e84c9a1322dcb95e2848Mark 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) { 408daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn prctl(PR_SET_NAME, "logd.reader"); 418daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn 420175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn char buffer[255]; 430175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 440175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1); 450175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (len <= 0) { 460175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn doSocketDelete(cli); 470175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return false; 480175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 490175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn buffer[len] = '\0'; 500175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn unsigned long tail = 0; 520175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _tail[] = " tail="; 530175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn char *cp = strstr(buffer, _tail); 540175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 550175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn tail = atol(cp + sizeof(_tail) - 1); 560175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 570175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 58fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn log_time start(log_time::EPOCH); 59fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn static const char _start[] = " start="; 60fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn cp = strstr(buffer, _start); 61fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn if (cp) { 62fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn // Parse errors will result in current time 63fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn start.strptime(cp + sizeof(_start) - 1, "%s.%q"); 64fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn } 65fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn unsigned int logMask = -1; 670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _logIds[] = " lids="; 680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp = strstr(buffer, _logIds); 690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn logMask = 0; 710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp += sizeof(_logIds) - 1; 720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn while (*cp && *cp != '\0') { 730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn int val = 0; 74fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn while (isdigit(*cp)) { 75fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn val = val * 10 + *cp - '0'; 760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn ++cp; 770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn logMask |= 1 << val; 790175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (*cp != ',') { 800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn break; 810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn ++cp; 830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pid_t pid = 0; 870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _pid[] = " pid="; 880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp = strstr(buffer, _pid); 890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 900175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pid = atol(cp + sizeof(_pid) - 1); 910175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 920175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 930175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn bool nonBlock = false; 940175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (strncmp(buffer, "dumpAndClose", 12) == 0) { 957391575afdd6c27bf444dcde7a140f1b17629b8cMark Salyzyn // Allow writer to get some cycles, and wait for pending notifications 967391575afdd6c27bf444dcde7a140f1b17629b8cMark Salyzyn sched_yield(); 977391575afdd6c27bf444dcde7a140f1b17629b8cMark Salyzyn LogTimeEntry::lock(); 987391575afdd6c27bf444dcde7a140f1b17629b8cMark Salyzyn LogTimeEntry::unlock(); 997391575afdd6c27bf444dcde7a140f1b17629b8cMark Salyzyn sched_yield(); 1000175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn nonBlock = true; 1010175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1020175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 103fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn // Convert realtime to monotonic time 104fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn if (start == log_time::EPOCH) { 105fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn start = LogTimeEntry::EPOCH; 106a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } else { 107a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn class LogFindStart { 108a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn const pid_t mPid; 109a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn const unsigned mLogMask; 110a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn bool startTimeSet; 111a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time &start; 112a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time last; 113a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 114a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn public: 115a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn LogFindStart(unsigned logMask, pid_t pid, log_time &start) 116a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn : mPid(pid) 117a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , mLogMask(logMask) 118a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , startTimeSet(false) 119a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , start(start) 120a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , last(LogTimeEntry::EPOCH) 121a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn { } 122a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 123a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn static bool callback(const LogBufferElement *element, void *obj) { 124a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn LogFindStart *me = reinterpret_cast<LogFindStart *>(obj); 125a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (!me->startTimeSet 126a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn && (!me->mPid || (me->mPid == element->getPid())) 127a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn && (me->mLogMask & (1 << element->getLogId()))) { 128a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (me->start == element->getRealTime()) { 129a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->start = element->getMonotonicTime(); 130a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->startTimeSet = true; 131a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } else { 132a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (me->start < element->getRealTime()) { 133a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->start = me->last; 134a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->startTimeSet = true; 135a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 136a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->last = element->getMonotonicTime(); 137a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 138a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 139a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn return false; 140a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 141a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 142a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn bool found() { return startTimeSet; } 143a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } logFindStart(logMask, pid, start); 144a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 145a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn logbuf().flushTo(cli, LogTimeEntry::EPOCH, 146a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn FlushCommand::hasReadLogs(cli), 147a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn logFindStart.callback, &logFindStart); 148a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 149a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (!logFindStart.found()) { 150a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (nonBlock) { 151a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn doSocketDelete(cli); 152a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn return false; 153a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 154a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time now(CLOCK_MONOTONIC); 155a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn start = now; 156a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 157fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn } 158fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 159fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn FlushCommand command(*this, nonBlock, tail, logMask, pid, start); 1600175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn command.runSocketCommand(cli); 1610175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return true; 1620175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 1630175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1640175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynvoid LogReader::doSocketDelete(SocketClient *cli) { 1650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes × = mLogbuf.mTimes; 1660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry::lock(); 1670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes::iterator it = times.begin(); 1680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn while(it != times.end()) { 1690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry *entry = (*it); 1700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (entry->mClient == cli) { 1710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn times.erase(it); 1720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn entry->release_Locked(); 1730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn break; 1740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn it++; 1760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry::unlock(); 1780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 179dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 180dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzynint LogReader::getLogSocket() { 181dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn static const char socketName[] = "logdr"; 182dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn int sock = android_get_control_socket(socketName); 183dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 184dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn if (sock < 0) { 185dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn sock = socket_local_server(socketName, 186dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn ANDROID_SOCKET_NAMESPACE_RESERVED, 187dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn SOCK_SEQPACKET); 188dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn } 189dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 190dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn return sock; 191dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn} 192