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
2766091f11f427587bf810d89b0f64be556e1cd168Mark SalyzynLogReader::LogReader(LogBuffer *logbuf) :
2866091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn        SocketListener(getLogSocket(), true),
2966091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn        mLogbuf(*logbuf) {
3066091f11f427587bf810d89b0f64be556e1cd168Mark 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;
980175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (strncmp(buffer, "dumpAndClose", 12) == 0) {
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;
117a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
118a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn        public:
11966091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn            LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence) :
12066091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn                    mPid(pid),
12166091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn                    mLogMask(logMask),
12266091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn                    startTimeSet(false),
12366091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn                    start(start),
12466091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn                    sequence(sequence),
12566091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn                    last(sequence) {
12666091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn            }
127a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
128f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn            static int callback(const LogBufferElement *element, void *obj) {
129a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                LogFindStart *me = reinterpret_cast<LogFindStart *>(obj);
130f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                if ((!me->mPid || (me->mPid == element->getPid()))
131a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                        && (me->mLogMask & (1 << element->getLogId()))) {
132a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                    if (me->start == element->getRealTime()) {
133f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                        me->sequence = element->getSequence();
134a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                        me->startTimeSet = true;
135f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                        return -1;
136a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                    } else {
137a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                        if (me->start < element->getRealTime()) {
138f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                            me->sequence = me->last;
139a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                            me->startTimeSet = true;
140f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                            return -1;
141a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                        }
142f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn                        me->last = element->getSequence();
143a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                    }
144a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                }
145a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                return false;
146a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            }
147a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
148a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            bool found() { return startTimeSet; }
149f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn        } logFindStart(logMask, pid, start, sequence);
150a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
151f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn        logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli),
152a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                         logFindStart.callback, &logFindStart);
153a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn
154a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn        if (!logFindStart.found()) {
155a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            if (nonBlock) {
156a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                doSocketDelete(cli);
157a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn                return false;
158a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn            }
159f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn            sequence = LogBufferElement::getCurrentSequence();
160a1c60cf80d0d1002576a6cf8aa395b295c6a272eMark Salyzyn        }
161fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    }
162fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
163f7c0f75275d0fde2d8b7614f1501f0ad0cd3a01cMark Salyzyn    FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
1640175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    command.runSocketCommand(cli);
1650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    return true;
1660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
1670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
1680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynvoid LogReader::doSocketDelete(SocketClient *cli) {
1690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    LastLogTimes &times = mLogbuf.mTimes;
1700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    LogTimeEntry::lock();
1710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    LastLogTimes::iterator it = times.begin();
1720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    while(it != times.end()) {
1730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        LogTimeEntry *entry = (*it);
1740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        if (entry->mClient == cli) {
1750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            times.erase(it);
1760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            entry->release_Locked();
1770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            break;
1780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        }
1790175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        it++;
1800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
1810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    LogTimeEntry::unlock();
1820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
183dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
184dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzynint LogReader::getLogSocket() {
185dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    static const char socketName[] = "logdr";
186dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    int sock = android_get_control_socket(socketName);
187dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
188dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    if (sock < 0) {
189dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn        sock = socket_local_server(socketName,
190dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
191dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn                                   SOCK_SEQPACKET);
192dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    }
193dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
194dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    return sock;
195dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn}
196