| /* |
| * Copyright (C) 2012-2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <pthread.h> |
| #include <sys/socket.h> |
| #include <sys/types.h> |
| #include <time.h> |
| |
| #include <list> |
| #include <memory> |
| |
| #include <log/log.h> |
| #include <sysutils/SocketClient.h> |
| |
| typedef unsigned int log_mask_t; |
| |
| class LogReader; |
| class LogBufferElement; |
| |
| class LogReaderThread { |
| static pthread_mutex_t timesLock; |
| bool mRelease = false; |
| bool leadingDropped; |
| pthread_cond_t threadTriggeredCondition; |
| pthread_t mThread; |
| LogReader& mReader; |
| static void* threadStart(void* me); |
| const log_mask_t mLogMask; |
| const pid_t mPid; |
| unsigned int skipAhead[LOG_ID_MAX]; |
| pid_t mLastTid[LOG_ID_MAX]; |
| unsigned long mCount; |
| unsigned long mTail; |
| unsigned long mIndex; |
| |
| public: |
| LogReaderThread(LogReader& reader, SocketClient* client, bool non_block, unsigned long tail, |
| log_mask_t log_mask, pid_t pid, log_time start_time, uint64_t sequence, |
| uint64_t timeout, bool privileged, bool can_read_security_logs); |
| |
| SocketClient* mClient; |
| log_time mStartTime; |
| uint64_t mStart; |
| struct timespec mTimeout; // CLOCK_MONOTONIC based timeout used for log wrapping. |
| const bool mNonBlock; |
| |
| // Protect List manipulations |
| static void wrlock() { pthread_mutex_lock(×Lock); } |
| static void rdlock() { pthread_mutex_lock(×Lock); } |
| static void unlock() { pthread_mutex_unlock(×Lock); } |
| |
| bool startReader_Locked(); |
| |
| void triggerReader_Locked() { pthread_cond_signal(&threadTriggeredCondition); } |
| |
| void triggerSkip_Locked(log_id_t id, unsigned int skip) { skipAhead[id] = skip; } |
| void cleanSkip_Locked(); |
| |
| void release_Locked() { |
| // gracefully shut down the socket. |
| shutdown(mClient->getSocket(), SHUT_RDWR); |
| mRelease = true; |
| pthread_cond_signal(&threadTriggeredCondition); |
| } |
| |
| bool isWatching(log_id_t id) const { return mLogMask & (1 << id); } |
| bool isWatchingMultiple(log_mask_t log_mask) const { return mLogMask & log_mask; } |
| // flushTo filter callbacks |
| static int FilterFirstPass(const LogBufferElement* element, void* me); |
| static int FilterSecondPass(const LogBufferElement* element, void* me); |
| |
| private: |
| bool privileged_; |
| bool can_read_security_logs_; |
| }; |
| |
| typedef std::list<std::unique_ptr<LogReaderThread>> LastLogTimes; |