LogReader.cpp revision a1c60cf80d0d1002576a6cf8aa395b295c6a272e
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> 190175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/socket.h> 200175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <cutils/sockets.h> 210175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 220175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "LogReader.h" 230175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "FlushCommand.h" 240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 250175b0747a1f55329109e84c9a1322dcb95e2848Mark SalyzynLogReader::LogReader(LogBuffer *logbuf) 260175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn : SocketListener("logdr", true) 270175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn , mLogbuf(*logbuf) 280175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn{ } 290175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 300175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// When we are notified a new log entry is available, inform 310175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn// all of our listening sockets. 320175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynvoid LogReader::notifyNewLog() { 330175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn FlushCommand command(*this); 340175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn runOnEachSocket(&command); 350175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 360175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 370175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynbool LogReader::onDataAvailable(SocketClient *cli) { 380175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn char buffer[255]; 390175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 400175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1); 410175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (len <= 0) { 420175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn doSocketDelete(cli); 430175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return false; 440175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 450175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn buffer[len] = '\0'; 460175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 470175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn unsigned long tail = 0; 480175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _tail[] = " tail="; 490175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn char *cp = strstr(buffer, _tail); 500175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn tail = atol(cp + sizeof(_tail) - 1); 520175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 530175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 54fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn log_time start(log_time::EPOCH); 55fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn static const char _start[] = " start="; 56fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn cp = strstr(buffer, _start); 57fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn if (cp) { 58fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn // Parse errors will result in current time 59fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn start.strptime(cp + sizeof(_start) - 1, "%s.%q"); 60fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn } 61fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 620175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn unsigned int logMask = -1; 630175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _logIds[] = " lids="; 640175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp = strstr(buffer, _logIds); 650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn logMask = 0; 670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp += sizeof(_logIds) - 1; 680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn while (*cp && *cp != '\0') { 690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn int val = 0; 70fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn while (isdigit(*cp)) { 71fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn val = val * 10 + *cp - '0'; 720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn ++cp; 730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn logMask |= 1 << val; 750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (*cp != ',') { 760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn break; 770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn ++cp; 790175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pid_t pid = 0; 830175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn static const char _pid[] = " pid="; 840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn cp = strstr(buffer, _pid); 850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (cp) { 860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn pid = atol(cp + sizeof(_pid) - 1); 870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn bool nonBlock = false; 900175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (strncmp(buffer, "dumpAndClose", 12) == 0) { 910175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn nonBlock = true; 920175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 930175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 94fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn // Convert realtime to monotonic time 95fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn if (start == log_time::EPOCH) { 96fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn start = LogTimeEntry::EPOCH; 97a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } else { 98a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn class LogFindStart { 99a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn const pid_t mPid; 100a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn const unsigned mLogMask; 101a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn bool startTimeSet; 102a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time &start; 103a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time last; 104a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 105a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn public: 106a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn LogFindStart(unsigned logMask, pid_t pid, log_time &start) 107a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn : mPid(pid) 108a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , mLogMask(logMask) 109a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , startTimeSet(false) 110a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , start(start) 111a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn , last(LogTimeEntry::EPOCH) 112a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn { } 113a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 114a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn static bool callback(const LogBufferElement *element, void *obj) { 115a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn LogFindStart *me = reinterpret_cast<LogFindStart *>(obj); 116a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (!me->startTimeSet 117a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn && (!me->mPid || (me->mPid == element->getPid())) 118a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn && (me->mLogMask & (1 << element->getLogId()))) { 119a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (me->start == element->getRealTime()) { 120a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->start = element->getMonotonicTime(); 121a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->startTimeSet = true; 122a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } else { 123a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (me->start < element->getRealTime()) { 124a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->start = me->last; 125a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->startTimeSet = true; 126a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 127a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn me->last = element->getMonotonicTime(); 128a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 129a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 130a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn return false; 131a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 132a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 133a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn bool found() { return startTimeSet; } 134a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } logFindStart(logMask, pid, start); 135a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 136a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn logbuf().flushTo(cli, LogTimeEntry::EPOCH, 137a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn FlushCommand::hasReadLogs(cli), 138a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn logFindStart.callback, &logFindStart); 139a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn 140a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (!logFindStart.found()) { 141a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn if (nonBlock) { 142a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn doSocketDelete(cli); 143a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn return false; 144a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 145a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn log_time now(CLOCK_MONOTONIC); 146a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn start = now; 147a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn } 148fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn } 149fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 150fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn FlushCommand command(*this, nonBlock, tail, logMask, pid, start); 1510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn command.runSocketCommand(cli); 1520175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn return true; 1530175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 1540175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn 1550175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynvoid LogReader::doSocketDelete(SocketClient *cli) { 1560175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes × = mLogbuf.mTimes; 1570175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry::lock(); 1580175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LastLogTimes::iterator it = times.begin(); 1590175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn while(it != times.end()) { 1600175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry *entry = (*it); 1610175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn if (entry->mClient == cli) { 1620175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn times.erase(it); 1630175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn entry->release_Locked(); 1640175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn break; 1650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn it++; 1670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn } 1680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn LogTimeEntry::unlock(); 1690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn} 170