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