1*598139dcSAndroid Build Coastguard Worker /* 2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project 3*598139dcSAndroid Build Coastguard Worker * 4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*598139dcSAndroid Build Coastguard Worker * 8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*598139dcSAndroid Build Coastguard Worker * 10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*598139dcSAndroid Build Coastguard Worker * limitations under the License. 15*598139dcSAndroid Build Coastguard Worker */ 16*598139dcSAndroid Build Coastguard Worker 17*598139dcSAndroid Build Coastguard Worker #pragma once 18*598139dcSAndroid Build Coastguard Worker 19*598139dcSAndroid Build Coastguard Worker #include <bitset> 20*598139dcSAndroid Build Coastguard Worker #include <list> 21*598139dcSAndroid Build Coastguard Worker #include <queue> 22*598139dcSAndroid Build Coastguard Worker 23*598139dcSAndroid Build Coastguard Worker #include "LogBuffer.h" 24*598139dcSAndroid Build Coastguard Worker #include "LogdLock.h" 25*598139dcSAndroid Build Coastguard Worker #include "SerializedLogChunk.h" 26*598139dcSAndroid Build Coastguard Worker #include "SerializedLogEntry.h" 27*598139dcSAndroid Build Coastguard Worker 28*598139dcSAndroid Build Coastguard Worker struct LogPosition { 29*598139dcSAndroid Build Coastguard Worker std::list<SerializedLogChunk>::iterator buffer_it; 30*598139dcSAndroid Build Coastguard Worker int read_offset; 31*598139dcSAndroid Build Coastguard Worker log_entryLogPosition32*598139dcSAndroid Build Coastguard Worker const SerializedLogEntry* log_entry() const { return buffer_it->log_entry(read_offset); } 33*598139dcSAndroid Build Coastguard Worker }; 34*598139dcSAndroid Build Coastguard Worker 35*598139dcSAndroid Build Coastguard Worker struct LogWithId { 36*598139dcSAndroid Build Coastguard Worker log_id_t log_id; 37*598139dcSAndroid Build Coastguard Worker const SerializedLogEntry* entry; 38*598139dcSAndroid Build Coastguard Worker }; 39*598139dcSAndroid Build Coastguard Worker 40*598139dcSAndroid Build Coastguard Worker // This class tracks the specific point where a FlushTo client has read through the logs. It 41*598139dcSAndroid Build Coastguard Worker // directly references the std::list<> iterators from the parent SerializedLogBuffer and the offset 42*598139dcSAndroid Build Coastguard Worker // into each log chunk where it has last read. All interactions with this class, except for its 43*598139dcSAndroid Build Coastguard Worker // construction, must be done with SerializedLogBuffer::lock_ held. 44*598139dcSAndroid Build Coastguard Worker class SerializedFlushToState : public FlushToState { 45*598139dcSAndroid Build Coastguard Worker public: 46*598139dcSAndroid Build Coastguard Worker // Initializes this state object. For each log buffer set in log_mask, this sets 47*598139dcSAndroid Build Coastguard Worker // logs_needed_from_next_position_. 48*598139dcSAndroid Build Coastguard Worker SerializedFlushToState(uint64_t start, LogMask log_mask, std::list<SerializedLogChunk>* logs) 49*598139dcSAndroid Build Coastguard Worker REQUIRES(logd_lock); 50*598139dcSAndroid Build Coastguard Worker 51*598139dcSAndroid Build Coastguard Worker // Decrease the reference of all referenced logs. This happens when a reader is disconnected. 52*598139dcSAndroid Build Coastguard Worker ~SerializedFlushToState() override; 53*598139dcSAndroid Build Coastguard Worker 54*598139dcSAndroid Build Coastguard Worker // Updates the state of log_positions_ and logs_needed_from_next_position_ then returns true if 55*598139dcSAndroid Build Coastguard Worker // there are any unread logs, false otherwise. 56*598139dcSAndroid Build Coastguard Worker bool HasUnreadLogs() REQUIRES(logd_lock); 57*598139dcSAndroid Build Coastguard Worker 58*598139dcSAndroid Build Coastguard Worker // Returns the next unread log and sets logs_needed_from_next_position_ to indicate that we're 59*598139dcSAndroid Build Coastguard Worker // waiting for more logs from the associated log buffer. 60*598139dcSAndroid Build Coastguard Worker LogWithId PopNextUnreadLog() REQUIRES(logd_lock); 61*598139dcSAndroid Build Coastguard Worker 62*598139dcSAndroid Build Coastguard Worker // If the parent log buffer prunes logs, the reference that this class contains may become 63*598139dcSAndroid Build Coastguard Worker // invalid, so this must be called first to drop the reference to buffer_it, if any. 64*598139dcSAndroid Build Coastguard Worker void Prune(log_id_t log_id) REQUIRES(logd_lock); 65*598139dcSAndroid Build Coastguard Worker 66*598139dcSAndroid Build Coastguard Worker private: 67*598139dcSAndroid Build Coastguard Worker // Set logs_needed_from_next_position_[i] to indicate if log_positions_[i] points to an unread 68*598139dcSAndroid Build Coastguard Worker // log or to the point at which the next log will appear. 69*598139dcSAndroid Build Coastguard Worker void UpdateLogsNeeded(log_id_t log_id) REQUIRES(logd_lock); 70*598139dcSAndroid Build Coastguard Worker 71*598139dcSAndroid Build Coastguard Worker // Create a LogPosition object for the given log_id by searching through the log chunks for the 72*598139dcSAndroid Build Coastguard Worker // first chunk and then first log entry within that chunk that is greater or equal to start(). 73*598139dcSAndroid Build Coastguard Worker void CreateLogPosition(log_id_t log_id) REQUIRES(logd_lock); 74*598139dcSAndroid Build Coastguard Worker 75*598139dcSAndroid Build Coastguard Worker // Checks to see if any log buffers set in logs_needed_from_next_position_ have new logs and 76*598139dcSAndroid Build Coastguard Worker // calls UpdateLogsNeeded() if so. 77*598139dcSAndroid Build Coastguard Worker void CheckForNewLogs() REQUIRES(logd_lock); 78*598139dcSAndroid Build Coastguard Worker 79*598139dcSAndroid Build Coastguard Worker std::list<SerializedLogChunk>* logs_ GUARDED_BY(logd_lock) = nullptr; 80*598139dcSAndroid Build Coastguard Worker // An optional structure that contains an iterator to the serialized log buffer and offset into 81*598139dcSAndroid Build Coastguard Worker // it that this logger should handle next. 82*598139dcSAndroid Build Coastguard Worker std::optional<LogPosition> log_positions_[LOG_ID_MAX] GUARDED_BY(logd_lock); 83*598139dcSAndroid Build Coastguard Worker // A bit for each log that is set if a given log_id has no logs or if this client has read all 84*598139dcSAndroid Build Coastguard Worker // of its logs. In order words: `logs_[i].empty() || (buffer_it == std::prev(logs_.end) && 85*598139dcSAndroid Build Coastguard Worker // next_log_position == logs_write_position_)`. These will be re-checked in each 86*598139dcSAndroid Build Coastguard Worker // loop in case new logs came in. 87*598139dcSAndroid Build Coastguard Worker std::bitset<LOG_ID_MAX> logs_needed_from_next_position_ GUARDED_BY(logd_lock) = {}; 88*598139dcSAndroid Build Coastguard Worker }; 89