diff options
author | Tom Cherry <tomcherry@google.com> | 2020-06-16 16:55:25 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-06-16 16:55:25 +0000 |
commit | 1e412e7d4e67dba0fc30591a0e00bb52bc5bb292 (patch) | |
tree | d695c4bd0bb962867ddec39c27cc20dcfa88f3d7 /logd/SerializedLogChunk.cpp | |
parent | be42841c61dc8914f89ef3d900955a3dd4e62388 (diff) | |
parent | 1a796bca57ef45d559e70dc05ad2df5cb77b8f64 (diff) |
Merge "logd: add a SerializedLogBuffer suitable for compression"
Diffstat (limited to 'logd/SerializedLogChunk.cpp')
-rw-r--r-- | logd/SerializedLogChunk.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/logd/SerializedLogChunk.cpp b/logd/SerializedLogChunk.cpp new file mode 100644 index 000000000..2516003c1 --- /dev/null +++ b/logd/SerializedLogChunk.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SerializedLogChunk.h" + +#include <android-base/logging.h> + +#include "CompressionEngine.h" + +SerializedLogChunk::~SerializedLogChunk() { + CHECK_EQ(reader_ref_count_, 0U); +} + +void SerializedLogChunk::Compress() { + if (compressed_log_.empty()) { + CompressionEngine::GetInstance().Compress({contents_.data(), write_offset_}, + compressed_log_); + LOG(INFO) << "Compressed Log, buffer max size: " << contents_.size() + << " size used: " << write_offset_ + << " compressed size: " << compressed_log_.size(); + } + contents_.resize(0); +} + +// TODO: Develop a better reference counting strategy to guard against the case where the writer is +// much faster than the reader, and we needlessly compess / decompress the logs. +void SerializedLogChunk::IncReaderRefCount() { + if (++reader_ref_count_ != 1 || writer_active_) { + return; + } + CompressionEngine::GetInstance().Decompress(compressed_log_, contents_, write_offset_); +} + +void SerializedLogChunk::DecReaderRefCount(bool compress) { + CHECK_NE(reader_ref_count_, 0U); + if (--reader_ref_count_ != 0) { + return; + } + if (compress && !writer_active_) { + Compress(); + } +} + +bool SerializedLogChunk::ClearUidLogs(uid_t uid, log_id_t log_id, LogStatistics* stats) { + CHECK_EQ(reader_ref_count_, 0U); + if (write_offset_ == 0) { + return true; + } + + IncReaderRefCount(); + + int read_offset = 0; + int new_write_offset = 0; + while (read_offset < write_offset_) { + const auto* entry = log_entry(read_offset); + if (entry->uid() == uid) { + read_offset += entry->total_len(); + if (stats != nullptr) { + stats->Subtract(entry->ToLogStatisticsElement(log_id)); + } + continue; + } + size_t entry_total_len = entry->total_len(); + if (read_offset != new_write_offset) { + memmove(contents_.data() + new_write_offset, contents_.data() + read_offset, + entry_total_len); + } + read_offset += entry_total_len; + new_write_offset += entry_total_len; + } + + if (new_write_offset == 0) { + DecReaderRefCount(false); + return true; + } + + // Clear the old compressed logs and set write_offset_ appropriately for DecReaderRefCount() + // to compress the new partially cleared log. + if (new_write_offset != write_offset_) { + compressed_log_.clear(); + write_offset_ = new_write_offset; + } + + DecReaderRefCount(true); + + return false; +} + +bool SerializedLogChunk::CanLog(size_t len) { + return write_offset_ + len <= contents_.size(); +} + +SerializedLogEntry* SerializedLogChunk::Log(uint64_t sequence, log_time realtime, uid_t uid, + pid_t pid, pid_t tid, const char* msg, uint16_t len) { + auto new_log_address = contents_.data() + write_offset_; + auto* entry = new (new_log_address) SerializedLogEntry(uid, pid, tid, sequence, realtime, len); + memcpy(entry->msg(), msg, len); + write_offset_ += entry->total_len(); + highest_sequence_number_ = sequence; + return entry; +}
\ No newline at end of file |