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 #include "SerializedLogChunk.h" 18 19 #include <android-base/logging.h> 20 21 #include "CompressionEngine.h" 22 #include "SerializedFlushToState.h" 23 ~SerializedLogChunk()24 SerializedLogChunk::~SerializedLogChunk() { 25 CHECK_EQ(reader_ref_count_, 0U); 26 } 27 FinishWriting()28 void SerializedLogChunk::FinishWriting() { 29 writer_active_ = false; 30 CHECK_EQ(compressed_log_.size(), 0U); 31 CompressionEngine::GetInstance().Compress(contents_, write_offset_, compressed_log_); 32 LOG(VERBOSE) << "Compressed Log, buffer max size: " << contents_.size() 33 << " size used: " << write_offset_ 34 << " compressed size: " << compressed_log_.size(); 35 if (reader_ref_count_ == 0) { 36 contents_.Resize(0); 37 } 38 } 39 40 // TODO: Develop a better reference counting strategy to guard against the case where the writer is 41 // much faster than the reader, and we needlessly compess / decompress the logs. IncReaderRefCount()42 void SerializedLogChunk::IncReaderRefCount() { 43 if (++reader_ref_count_ != 1 || writer_active_) { 44 return; 45 } 46 contents_.Resize(write_offset_); 47 CompressionEngine::GetInstance().Decompress(compressed_log_, contents_); 48 } 49 DecReaderRefCount()50 void SerializedLogChunk::DecReaderRefCount() { 51 CHECK_NE(reader_ref_count_, 0U); 52 if (--reader_ref_count_ != 0) { 53 return; 54 } 55 if (!writer_active_) { 56 contents_.Resize(0); 57 } 58 } 59 AttachReader(SerializedFlushToState * reader)60 void SerializedLogChunk::AttachReader(SerializedFlushToState* reader) { 61 readers_.emplace_back(reader); 62 IncReaderRefCount(); 63 } 64 DetachReader(SerializedFlushToState * reader)65 void SerializedLogChunk::DetachReader(SerializedFlushToState* reader) { 66 auto it = std::find(readers_.begin(), readers_.end(), reader); 67 CHECK(readers_.end() != it); 68 readers_.erase(it); 69 DecReaderRefCount(); 70 } 71 NotifyReadersOfPrune(log_id_t log_id)72 void SerializedLogChunk::NotifyReadersOfPrune(log_id_t log_id) { 73 // Readers will call DetachReader() in their Prune() call, so we make a copy of the list first. 74 auto readers = readers_; 75 for (auto& reader : readers) { 76 reader->Prune(log_id); 77 } 78 } 79 CanLog(size_t len)80 bool SerializedLogChunk::CanLog(size_t len) { 81 return write_offset_ + len <= contents_.size(); 82 } 83 Log(uint64_t sequence,log_time realtime,uid_t uid,pid_t pid,pid_t tid,const char * msg,uint16_t len)84 SerializedLogEntry* SerializedLogChunk::Log(uint64_t sequence, log_time realtime, uid_t uid, 85 pid_t pid, pid_t tid, const char* msg, uint16_t len) { 86 auto new_log_address = contents_.data() + write_offset_; 87 auto* entry = new (new_log_address) SerializedLogEntry(uid, pid, tid, sequence, realtime, len); 88 memcpy(entry->msg(), msg, len); 89 write_offset_ += entry->total_len(); 90 highest_sequence_number_ = sequence; 91 return entry; 92 } 93