xref: /aosp_15_r20/system/logging/logd/SerializedLogChunk.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
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