1 /* 2 * Copyright (C) 2020 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 #pragma once 18 19 #include <bitset> 20 #include <list> 21 #include <queue> 22 23 #include "LogBuffer.h" 24 #include "LogdLock.h" 25 #include "SerializedLogChunk.h" 26 #include "SerializedLogEntry.h" 27 28 struct LogPosition { 29 std::list<SerializedLogChunk>::iterator buffer_it; 30 int read_offset; 31 log_entryLogPosition32 const SerializedLogEntry* log_entry() const { return buffer_it->log_entry(read_offset); } 33 }; 34 35 struct LogWithId { 36 log_id_t log_id; 37 const SerializedLogEntry* entry; 38 }; 39 40 // This class tracks the specific point where a FlushTo client has read through the logs. It 41 // directly references the std::list<> iterators from the parent SerializedLogBuffer and the offset 42 // into each log chunk where it has last read. All interactions with this class, except for its 43 // construction, must be done with SerializedLogBuffer::lock_ held. 44 class SerializedFlushToState : public FlushToState { 45 public: 46 // Initializes this state object. For each log buffer set in log_mask, this sets 47 // logs_needed_from_next_position_. 48 SerializedFlushToState(uint64_t start, LogMask log_mask, std::list<SerializedLogChunk>* logs) 49 REQUIRES(logd_lock); 50 51 // Decrease the reference of all referenced logs. This happens when a reader is disconnected. 52 ~SerializedFlushToState() override; 53 54 // Updates the state of log_positions_ and logs_needed_from_next_position_ then returns true if 55 // there are any unread logs, false otherwise. 56 bool HasUnreadLogs() REQUIRES(logd_lock); 57 58 // Returns the next unread log and sets logs_needed_from_next_position_ to indicate that we're 59 // waiting for more logs from the associated log buffer. 60 LogWithId PopNextUnreadLog() REQUIRES(logd_lock); 61 62 // If the parent log buffer prunes logs, the reference that this class contains may become 63 // invalid, so this must be called first to drop the reference to buffer_it, if any. 64 void Prune(log_id_t log_id) REQUIRES(logd_lock); 65 66 private: 67 // Set logs_needed_from_next_position_[i] to indicate if log_positions_[i] points to an unread 68 // log or to the point at which the next log will appear. 69 void UpdateLogsNeeded(log_id_t log_id) REQUIRES(logd_lock); 70 71 // Create a LogPosition object for the given log_id by searching through the log chunks for the 72 // first chunk and then first log entry within that chunk that is greater or equal to start(). 73 void CreateLogPosition(log_id_t log_id) REQUIRES(logd_lock); 74 75 // Checks to see if any log buffers set in logs_needed_from_next_position_ have new logs and 76 // calls UpdateLogsNeeded() if so. 77 void CheckForNewLogs() REQUIRES(logd_lock); 78 79 std::list<SerializedLogChunk>* logs_ GUARDED_BY(logd_lock) = nullptr; 80 // An optional structure that contains an iterator to the serialized log buffer and offset into 81 // it that this logger should handle next. 82 std::optional<LogPosition> log_positions_[LOG_ID_MAX] GUARDED_BY(logd_lock); 83 // A bit for each log that is set if a given log_id has no logs or if this client has read all 84 // of its logs. In order words: `logs_[i].empty() || (buffer_it == std::prev(logs_.end) && 85 // next_log_position == logs_write_position_)`. These will be re-checked in each 86 // loop in case new logs came in. 87 std::bitset<LOG_ID_MAX> logs_needed_from_next_position_ GUARDED_BY(logd_lock) = {}; 88 }; 89