blob: 2a04880e4dadf49fca2411730ca95acb7309e9ef [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
2 * Copyright (C) 2014 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
Mark Salyzynb75cce02015-11-30 11:35:56 -080017#include <errno.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070018#include <sys/prctl.h>
19
Mark Salyzyn0175b072014-02-26 09:50:16 -080020#include "FlushCommand.h"
21#include "LogBuffer.h"
22#include "LogTimes.h"
23#include "LogReader.h"
24
25pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
26
Mark Salyzyn0175b072014-02-26 09:50:16 -080027LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
28 bool nonBlock, unsigned long tail,
Mark Salyzynfa3716b2014-02-14 16:05:05 -080029 unsigned int logMask, pid_t pid,
Mark Salyzynb75cce02015-11-30 11:35:56 -080030 uint64_t start, uint64_t timeout) :
Mark Salyzyn77187782015-05-12 15:21:31 -070031 mRefCount(1),
32 mRelease(false),
33 mError(false),
34 threadRunning(false),
Mark Salyzyn047cc072015-06-04 13:35:30 -070035 leadingDropped(false),
Mark Salyzyn77187782015-05-12 15:21:31 -070036 mReader(reader),
37 mLogMask(logMask),
38 mPid(pid),
39 mCount(0),
40 mTail(tail),
41 mIndex(0),
42 mClient(client),
43 mStart(start),
44 mNonBlock(nonBlock),
45 mEnd(LogBufferElement::getCurrentSequence()) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080046 mTimeout.tv_sec = timeout / NS_PER_SEC;
47 mTimeout.tv_nsec = timeout % NS_PER_SEC;
Mark Salyzyn77187782015-05-12 15:21:31 -070048 pthread_cond_init(&threadTriggeredCondition, NULL);
49 cleanSkip_Locked();
Mark Salyzyna16f7612014-08-07 08:16:52 -070050}
Mark Salyzyn0175b072014-02-26 09:50:16 -080051
52void LogTimeEntry::startReader_Locked(void) {
Mark Salyzyn765f7822014-04-04 12:47:44 -070053 pthread_attr_t attr;
54
Mark Salyzyn0175b072014-02-26 09:50:16 -080055 threadRunning = true;
Mark Salyzyn765f7822014-04-04 12:47:44 -070056
57 if (!pthread_attr_init(&attr)) {
58 if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
59 if (!pthread_create(&mThread, &attr,
60 LogTimeEntry::threadStart, this)) {
61 pthread_attr_destroy(&attr);
62 return;
63 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080064 }
Mark Salyzyn765f7822014-04-04 12:47:44 -070065 pthread_attr_destroy(&attr);
Mark Salyzyn0175b072014-02-26 09:50:16 -080066 }
Mark Salyzyn765f7822014-04-04 12:47:44 -070067 threadRunning = false;
68 if (mClient) {
69 mClient->decRef();
70 }
71 decRef_Locked();
Mark Salyzyn0175b072014-02-26 09:50:16 -080072}
73
74void LogTimeEntry::threadStop(void *obj) {
75 LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
76
77 lock();
78
Mark Salyzyn0175b072014-02-26 09:50:16 -080079 if (me->mNonBlock) {
80 me->error_Locked();
81 }
82
83 SocketClient *client = me->mClient;
84
85 if (me->isError_Locked()) {
86 LogReader &reader = me->mReader;
87 LastLogTimes &times = reader.logbuf().mTimes;
88
89 LastLogTimes::iterator it = times.begin();
90 while(it != times.end()) {
91 if (*it == me) {
92 times.erase(it);
Mark Salyzync3484162016-03-01 14:59:32 -080093 me->release_nodelete_Locked();
Mark Salyzyn0175b072014-02-26 09:50:16 -080094 break;
95 }
96 it++;
97 }
98
99 me->mClient = NULL;
100 reader.release(client);
101 }
102
103 if (client) {
104 client->decRef();
105 }
106
Mark Salyzyna16f7612014-08-07 08:16:52 -0700107 me->threadRunning = false;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800108 me->decRef_Locked();
109
110 unlock();
111}
112
113void *LogTimeEntry::threadStart(void *obj) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700114 prctl(PR_SET_NAME, "logd.reader.per");
115
Mark Salyzyn0175b072014-02-26 09:50:16 -0800116 LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
117
118 pthread_cleanup_push(threadStop, obj);
119
120 SocketClient *client = me->mClient;
121 if (!client) {
122 me->error();
Mark Salyzyna16f7612014-08-07 08:16:52 -0700123 return NULL;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800124 }
125
126 LogBuffer &logbuf = me->mReader.logbuf();
127
128 bool privileged = FlushCommand::hasReadLogs(client);
Mark Salyzyn8fa88962016-01-26 14:32:35 -0800129 bool security = FlushCommand::hasSecurityLogs(client);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800130
Mark Salyzyn047cc072015-06-04 13:35:30 -0700131 me->leadingDropped = true;
132
Mark Salyzyn0175b072014-02-26 09:50:16 -0800133 lock();
134
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700135 uint64_t start = me->mStart;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800136
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700137 while (me->threadRunning && !me->isError_Locked()) {
Mark Salyzynb75cce02015-11-30 11:35:56 -0800138
139 if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
140 if (pthread_cond_timedwait(&me->threadTriggeredCondition,
141 &timesLock,
142 &me->mTimeout) == ETIMEDOUT) {
143 me->mTimeout.tv_sec = 0;
144 me->mTimeout.tv_nsec = 0;
145 }
146 if (!me->threadRunning || me->isError_Locked()) {
147 break;
148 }
149 }
150
Mark Salyzyn0175b072014-02-26 09:50:16 -0800151 unlock();
152
153 if (me->mTail) {
Mark Salyzyn8fa88962016-01-26 14:32:35 -0800154 logbuf.flushTo(client, start, privileged, security, FilterFirstPass, me);
Mark Salyzyn047cc072015-06-04 13:35:30 -0700155 me->leadingDropped = true;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800156 }
Mark Salyzyn8fa88962016-01-26 14:32:35 -0800157 start = logbuf.flushTo(client, start, privileged, security, FilterSecondPass, me);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800158
Mark Salyzyna16f7612014-08-07 08:16:52 -0700159 lock();
160
Mark Salyzyn0175b072014-02-26 09:50:16 -0800161 if (start == LogBufferElement::FLUSH_ERROR) {
Mark Salyzyna16f7612014-08-07 08:16:52 -0700162 me->error_Locked();
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700163 break;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800164 }
165
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700166 me->mStart = start + 1;
167
Mark Salyzyna16f7612014-08-07 08:16:52 -0700168 if (me->mNonBlock || !me->threadRunning || me->isError_Locked()) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800169 break;
170 }
171
TraianX Schiauda6495d2014-12-17 10:53:41 +0200172 me->cleanSkip_Locked();
173
Mark Salyzynb75cce02015-11-30 11:35:56 -0800174 if (!me->mTimeout.tv_sec && !me->mTimeout.tv_nsec) {
175 pthread_cond_wait(&me->threadTriggeredCondition, &timesLock);
176 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800177 }
178
179 unlock();
180
Mark Salyzyn0175b072014-02-26 09:50:16 -0800181 pthread_cleanup_pop(true);
182
183 return NULL;
184}
185
186// A first pass to count the number of elements
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800187int LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800188 LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
189
190 LogTimeEntry::lock();
191
Mark Salyzyn047cc072015-06-04 13:35:30 -0700192 if (me->leadingDropped) {
193 if (element->getDropped()) {
194 LogTimeEntry::unlock();
195 return false;
196 }
197 me->leadingDropped = false;
198 }
199
Mark Salyzyn0175b072014-02-26 09:50:16 -0800200 if (me->mCount == 0) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800201 me->mStart = element->getSequence();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800202 }
203
204 if ((!me->mPid || (me->mPid == element->getPid()))
TraianX Schiauda6495d2014-12-17 10:53:41 +0200205 && (me->isWatching(element->getLogId()))) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800206 ++me->mCount;
207 }
208
209 LogTimeEntry::unlock();
210
211 return false;
212}
213
214// A second pass to send the selected elements
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800215int LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800216 LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
217
218 LogTimeEntry::lock();
219
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800220 me->mStart = element->getSequence();
TraianX Schiauda6495d2014-12-17 10:53:41 +0200221
222 if (me->skipAhead[element->getLogId()]) {
223 me->skipAhead[element->getLogId()]--;
Mark Salyzyn8d7656b2014-06-05 15:58:43 -0700224 goto skip;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800225 }
226
Mark Salyzyn047cc072015-06-04 13:35:30 -0700227 if (me->leadingDropped) {
228 if (element->getDropped()) {
229 goto skip;
230 }
231 me->leadingDropped = false;
232 }
233
Mark Salyzyn0175b072014-02-26 09:50:16 -0800234 // Truncate to close race between first and second pass
235 if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800236 goto stop;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800237 }
238
TraianX Schiauda6495d2014-12-17 10:53:41 +0200239 if (!me->isWatching(element->getLogId())) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800240 goto skip;
241 }
242
243 if (me->mPid && (me->mPid != element->getPid())) {
244 goto skip;
245 }
246
247 if (me->isError_Locked()) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800248 goto stop;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800249 }
250
251 if (!me->mTail) {
252 goto ok;
253 }
254
255 ++me->mIndex;
256
257 if ((me->mCount > me->mTail) && (me->mIndex <= (me->mCount - me->mTail))) {
258 goto skip;
259 }
260
261 if (!me->mNonBlock) {
262 me->mTail = 0;
263 }
264
265ok:
TraianX Schiauda6495d2014-12-17 10:53:41 +0200266 if (!me->skipAhead[element->getLogId()]) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800267 LogTimeEntry::unlock();
268 return true;
269 }
270 // FALLTHRU
271
272skip:
273 LogTimeEntry::unlock();
274 return false;
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800275
276stop:
277 LogTimeEntry::unlock();
278 return -1;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800279}
TraianX Schiauda6495d2014-12-17 10:53:41 +0200280
281void LogTimeEntry::cleanSkip_Locked(void) {
282 for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1)) {
283 skipAhead[i] = 0;
284 }
285}