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