1 /* 2 * Copyright (C) 2012-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 17 #include <stdlib.h> 18 19 #include "FlushCommand.h" 20 #include "LogBufferElement.h" 21 #include "LogCommand.h" 22 #include "LogReader.h" 23 #include "LogTimes.h" 24 FlushCommand(LogReader & reader,bool nonBlock,unsigned long tail,unsigned int logMask,pid_t pid,uint64_t start)25 FlushCommand::FlushCommand(LogReader &reader, 26 bool nonBlock, 27 unsigned long tail, 28 unsigned int logMask, 29 pid_t pid, 30 uint64_t start) : 31 mReader(reader), 32 mNonBlock(nonBlock), 33 mTail(tail), 34 mLogMask(logMask), 35 mPid(pid), 36 mStart(start) { 37 } 38 39 // runSocketCommand is called once for every open client on the 40 // log reader socket. Here we manage and associated the reader 41 // client tracking and log region locks LastLogTimes list of 42 // LogTimeEntrys, and spawn a transitory per-client thread to 43 // work at filing data to the socket. 44 // 45 // global LogTimeEntry::lock() is used to protect access, 46 // reference counts are used to ensure that individual 47 // LogTimeEntry lifetime is managed when not protected. runSocketCommand(SocketClient * client)48 void FlushCommand::runSocketCommand(SocketClient *client) { 49 LogTimeEntry *entry = NULL; 50 LastLogTimes × = mReader.logbuf().mTimes; 51 52 LogTimeEntry::lock(); 53 LastLogTimes::iterator it = times.begin(); 54 while(it != times.end()) { 55 entry = (*it); 56 if (entry->mClient == client) { 57 entry->triggerReader_Locked(); 58 if (entry->runningReader_Locked()) { 59 LogTimeEntry::unlock(); 60 return; 61 } 62 entry->incRef_Locked(); 63 break; 64 } 65 it++; 66 } 67 68 if (it == times.end()) { 69 // Create LogTimeEntry in notifyNewLog() ? 70 if (mTail == (unsigned long) -1) { 71 LogTimeEntry::unlock(); 72 return; 73 } 74 entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart); 75 times.push_front(entry); 76 } 77 78 client->incRef(); 79 80 // release client and entry reference counts once done 81 entry->startReader_Locked(); 82 LogTimeEntry::unlock(); 83 } 84 hasReadLogs(SocketClient * client)85 bool FlushCommand::hasReadLogs(SocketClient *client) { 86 return clientHasLogCredentials(client); 87 } 88