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