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 &times = 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