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 <sys/types.h> 20 21 #include <list> 22 #include <vector> 23 24 #include <android-base/logging.h> 25 26 #include "LogWriter.h" 27 #include "LogdLock.h" 28 #include "SerializedData.h" 29 #include "SerializedLogEntry.h" 30 31 class SerializedFlushToState; 32 33 class SerializedLogChunk { 34 public: 35 friend void VerifyChunks(const std::list<SerializedLogChunk>& expected, 36 const std::list<SerializedLogChunk>& chunks); 37 38 class LogEntryIterator { 39 public: LogEntryIterator(SerializedLogChunk & chunk,int read_offset_)40 LogEntryIterator(SerializedLogChunk& chunk, int read_offset_) 41 : chunk_(chunk), read_offset_(read_offset_) {} 42 43 LogEntryIterator& operator++() { 44 read_offset_ += chunk_.log_entry(read_offset_)->total_len(); 45 return *this; 46 } 47 48 bool operator!=(const LogEntryIterator& other) const { 49 return read_offset_ != other.read_offset_; 50 } 51 const SerializedLogEntry& operator*() const { return *chunk_.log_entry(read_offset_); } 52 53 private: 54 SerializedLogChunk& chunk_; 55 int read_offset_; 56 }; 57 SerializedLogChunk(size_t size)58 explicit SerializedLogChunk(size_t size) : contents_(size) {} 59 SerializedLogChunk(SerializedLogChunk&& other) noexcept = default; 60 ~SerializedLogChunk(); 61 62 void FinishWriting(); 63 void IncReaderRefCount(); 64 void DecReaderRefCount(); 65 void AttachReader(SerializedFlushToState* reader); 66 void DetachReader(SerializedFlushToState* reader); 67 68 void NotifyReadersOfPrune(log_id_t log_id) REQUIRES(logd_lock); 69 70 bool CanLog(size_t len); 71 SerializedLogEntry* Log(uint64_t sequence, log_time realtime, uid_t uid, pid_t pid, pid_t tid, 72 const char* msg, uint16_t len); 73 74 // If this buffer has been compressed, we only consider its compressed size when accounting for 75 // memory consumption for pruning. This is since the uncompressed log is only by used by 76 // readers, and thus not a representation of how much these logs cost to keep in memory. PruneSize()77 size_t PruneSize() const { 78 return sizeof(*this) + (compressed_log_.size() ?: contents_.size()); 79 } 80 log_entry(int offset)81 const SerializedLogEntry* log_entry(int offset) const { 82 CHECK(writer_active_ || reader_ref_count_ > 0); 83 return reinterpret_cast<const SerializedLogEntry*>(data() + offset); 84 } data()85 const uint8_t* data() const { return contents_.data(); } write_offset()86 int write_offset() const { return write_offset_; } highest_sequence_number()87 uint64_t highest_sequence_number() const { return highest_sequence_number_; } 88 begin()89 LogEntryIterator begin() { return LogEntryIterator(*this, 0); } 90 end()91 LogEntryIterator end() { return LogEntryIterator(*this, write_offset_); } 92 93 // Exposed for testing reader_ref_count()94 uint32_t reader_ref_count() const { return reader_ref_count_; } 95 96 private: 97 // The decompressed contents of this log buffer. Deallocated when the ref_count reaches 0 and 98 // writer_active_ is false. 99 SerializedData contents_; 100 int write_offset_ = 0; 101 uint32_t reader_ref_count_ = 0; 102 bool writer_active_ = true; 103 uint64_t highest_sequence_number_ = 1; 104 SerializedData compressed_log_; 105 std::vector<SerializedFlushToState*> readers_; 106 }; 107