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 typedef unsigned int log_mask_t;
30 
31 class LogReader;
32 class LogBufferElement;
33 
34 class LogTimeEntry {
35     static pthread_mutex_t timesLock;
36     unsigned int mRefCount;
37     bool mRelease;
38     bool mError;
39     bool threadRunning;
40     bool leadingDropped;
41     pthread_cond_t threadTriggeredCondition;
42     pthread_t mThread;
43     LogReader& mReader;
44     static void* threadStart(void* me);
45     static void threadStop(void* me);
46     const log_mask_t mLogMask;
47     const pid_t mPid;
48     unsigned int skipAhead[LOG_ID_MAX];
49     pid_t mLastTid[LOG_ID_MAX];
50     unsigned long mCount;
51     unsigned long mTail;
52     unsigned long mIndex;
53 
54    public:
55     LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
56                  unsigned long tail, log_mask_t logMask, pid_t pid,
57                  log_time start, uint64_t timeout);
58 
59     SocketClient* mClient;
60     log_time mStart;
61     struct timespec mTimeout;
62     const bool mNonBlock;
63     const log_time mEnd;  // only relevant if mNonBlock
64 
65     // Protect List manipulations
wrlock(void)66     static void wrlock(void) {
67         pthread_mutex_lock(&timesLock);
68     }
rdlock(void)69     static void rdlock(void) {
70         pthread_mutex_lock(&timesLock);
71     }
unlock(void)72     static void unlock(void) {
73         pthread_mutex_unlock(&timesLock);
74     }
75 
76     void startReader_Locked(void);
77 
runningReader_Locked(void)78     bool runningReader_Locked(void) const {
79         return threadRunning || mRelease || mError || mNonBlock;
80     }
triggerReader_Locked(void)81     void triggerReader_Locked(void) {
82         pthread_cond_signal(&threadTriggeredCondition);
83     }
84 
triggerSkip_Locked(log_id_t id,unsigned int skip)85     void triggerSkip_Locked(log_id_t id, unsigned int skip) {
86         skipAhead[id] = skip;
87     }
88     void cleanSkip_Locked(void);
89 
90     // These called after LogTimeEntry removed from list, lock implicitly held
release_nodelete_Locked(void)91     void release_nodelete_Locked(void) {
92         mRelease = true;
93         pthread_cond_signal(&threadTriggeredCondition);
94         // assumes caller code path will call decRef_Locked()
95     }
96 
release_Locked(void)97     void release_Locked(void) {
98         mRelease = true;
99         pthread_cond_signal(&threadTriggeredCondition);
100         if (mRefCount || threadRunning) {
101             return;
102         }
103         // No one else is holding a reference to this
104         delete this;
105     }
106 
107     // Called to mark socket in jeopardy
error_Locked(void)108     void error_Locked(void) {
109         mError = true;
110     }
error(void)111     void error(void) {
112         wrlock();
113         error_Locked();
114         unlock();
115     }
116 
isError_Locked(void)117     bool isError_Locked(void) const {
118         return mRelease || mError;
119     }
120 
121     // Mark Used
122     //  Locking implied, grabbed when protection around loop iteration
incRef_Locked(void)123     void incRef_Locked(void) {
124         ++mRefCount;
125     }
126 
owned_Locked(void)127     bool owned_Locked(void) const {
128         return mRefCount != 0;
129     }
130 
decRef_Locked(void)131     void decRef_Locked(void) {
132         if ((mRefCount && --mRefCount) || !mRelease || threadRunning) {
133             return;
134         }
135         // No one else is holding a reference to this
136         delete this;
137     }
isWatching(log_id_t id)138     bool isWatching(log_id_t id) const {
139         return mLogMask & (1 << id);
140     }
isWatchingMultiple(log_mask_t logMask)141     bool isWatchingMultiple(log_mask_t logMask) const {
142         return mLogMask & logMask;
143     }
144     // flushTo filter callbacks
145     static int FilterFirstPass(const LogBufferElement* element, void* me);
146     static int FilterSecondPass(const LogBufferElement* element, void* me);
147 };
148 
149 typedef std::list<LogTimeEntry*> LastLogTimes;
150 
151 #endif  // _LOGD_LOG_TIMES_H__
152