1 /*
2  * Copyright (C) 2012-2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _LOGD_LOG_TIMES_H__
18 #define _LOGD_LOG_TIMES_H__
19 
20 #include <pthread.h>
21 #include <sys/types.h>
22 #include <time.h>
23 
24 #include <list>
25 
26 #include <log/log.h>
27 #include <sysutils/SocketClient.h>
28 
29 class LogReader;
30 class LogBufferElement;
31 
32 class LogTimeEntry {
33     static pthread_mutex_t timesLock;
34     unsigned int mRefCount;
35     bool mRelease;
36     bool mError;
37     bool threadRunning;
38     bool leadingDropped;
39     pthread_cond_t threadTriggeredCondition;
40     pthread_t mThread;
41     LogReader& mReader;
42     static void* threadStart(void* me);
43     static void threadStop(void* me);
44     const unsigned int mLogMask;
45     const pid_t mPid;
46     unsigned int skipAhead[LOG_ID_MAX];
47     pid_t mLastTid[LOG_ID_MAX];
48     unsigned long mCount;
49     unsigned long mTail;
50     unsigned long mIndex;
51 
52    public:
53     LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
54                  unsigned long tail, unsigned int logMask, pid_t pid,
55                  log_time start, uint64_t timeout);
56 
57     SocketClient* mClient;
58     log_time mStart;
59     struct timespec mTimeout;
60     const bool mNonBlock;
61     const log_time mEnd;  // only relevant if mNonBlock
62 
63     // Protect List manipulations
lock(void)64     static void lock(void) {
65         pthread_mutex_lock(&timesLock);
66     }
unlock(void)67     static void unlock(void) {
68         pthread_mutex_unlock(&timesLock);
69     }
70 
71     void startReader_Locked(void);
72 
runningReader_Locked(void)73     bool runningReader_Locked(void) const {
74         return threadRunning || mRelease || mError || mNonBlock;
75     }
triggerReader_Locked(void)76     void triggerReader_Locked(void) {
77         pthread_cond_signal(&threadTriggeredCondition);
78     }
79 
triggerSkip_Locked(log_id_t id,unsigned int skip)80     void triggerSkip_Locked(log_id_t id, unsigned int skip) {
81         skipAhead[id] = skip;
82     }
83     void cleanSkip_Locked(void);
84 
85     // These called after LogTimeEntry removed from list, lock implicitly held
release_nodelete_Locked(void)86     void release_nodelete_Locked(void) {
87         mRelease = true;
88         pthread_cond_signal(&threadTriggeredCondition);
89         // assumes caller code path will call decRef_Locked()
90     }
91 
release_Locked(void)92     void release_Locked(void) {
93         mRelease = true;
94         pthread_cond_signal(&threadTriggeredCondition);
95         if (mRefCount || threadRunning) {
96             return;
97         }
98         // No one else is holding a reference to this
99         delete this;
100     }
101 
102     // Called to mark socket in jeopardy
error_Locked(void)103     void error_Locked(void) {
104         mError = true;
105     }
error(void)106     void error(void) {
107         lock();
108         error_Locked();
109         unlock();
110     }
111 
isError_Locked(void)112     bool isError_Locked(void) const {
113         return mRelease || mError;
114     }
115 
116     // Mark Used
117     //  Locking implied, grabbed when protection around loop iteration
incRef_Locked(void)118     void incRef_Locked(void) {
119         ++mRefCount;
120     }
121 
owned_Locked(void)122     bool owned_Locked(void) const {
123         return mRefCount != 0;
124     }
125 
decRef_Locked(void)126     void decRef_Locked(void) {
127         if ((mRefCount && --mRefCount) || !mRelease || threadRunning) {
128             return;
129         }
130         // No one else is holding a reference to this
131         delete this;
132     }
isWatching(log_id_t id)133     bool isWatching(log_id_t id) {
134         return (mLogMask & (1 << id)) != 0;
135     }
136     // flushTo filter callbacks
137     static int FilterFirstPass(const LogBufferElement* element, void* me);
138     static int FilterSecondPass(const LogBufferElement* element, void* me);
139 };
140 
141 typedef std::list<LogTimeEntry*> LastLogTimes;
142 
143 #endif  // _LOGD_LOG_TIMES_H__
144