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