1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <libsnapshot/snapshot_stats.h>
16
17 #include <sstream>
18
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include "utility.h"
22
23 namespace android {
24 namespace snapshot {
25
GetInstance(SnapshotManager & parent)26 SnapshotMergeStats* SnapshotMergeStats::GetInstance(SnapshotManager& parent) {
27 static SnapshotMergeStats g_instance(parent.GetMergeStateFilePath());
28 CHECK(g_instance.path_ == parent.GetMergeStateFilePath());
29 return &g_instance;
30 }
31
SnapshotMergeStats(const std::string & path)32 SnapshotMergeStats::SnapshotMergeStats(const std::string& path) : path_(path), running_(false) {}
33
ReadState()34 bool SnapshotMergeStats::ReadState() {
35 std::string contents;
36 if (!android::base::ReadFileToString(path_, &contents)) {
37 PLOG(INFO) << "Read merge statistics file failed";
38 return false;
39 }
40 if (!report_.ParseFromString(contents)) {
41 LOG(ERROR) << "Unable to parse merge statistics file as SnapshotMergeReport";
42 return false;
43 }
44 return true;
45 }
46
WriteState()47 bool SnapshotMergeStats::WriteState() {
48 std::string contents;
49 if (!report_.SerializeToString(&contents)) {
50 LOG(ERROR) << "Unable to serialize SnapshotMergeStats.";
51 return false;
52 }
53 if (!WriteStringToFileAtomic(contents, path_)) {
54 PLOG(ERROR) << "Could not write to merge statistics file";
55 return false;
56 }
57 return true;
58 }
59
DeleteState()60 bool SnapshotMergeStats::DeleteState() {
61 std::string error;
62 if (!android::base::RemoveFileIfExists(path_, &error)) {
63 LOG(ERROR) << "Failed to remove merge statistics file " << path_ << ": " << error;
64 return false;
65 }
66 return true;
67 }
68
Start()69 bool SnapshotMergeStats::Start() {
70 if (running_) {
71 LOG(ERROR) << "SnapshotMergeStats running_ == " << running_;
72 return false;
73 }
74 running_ = true;
75
76 start_time_ = std::chrono::steady_clock::now();
77 if (ReadState()) {
78 report_.set_resume_count(report_.resume_count() + 1);
79 } else {
80 report_.set_resume_count(0);
81 report_.set_state(UpdateState::None);
82 }
83
84 return WriteState();
85 }
86
set_state(android::snapshot::UpdateState state,bool using_compression)87 void SnapshotMergeStats::set_state(android::snapshot::UpdateState state, bool using_compression) {
88 report_.set_state(state);
89 report_.set_compression_enabled(using_compression);
90 }
91
set_cow_file_size(uint64_t cow_file_size)92 void SnapshotMergeStats::set_cow_file_size(uint64_t cow_file_size) {
93 report_.set_cow_file_size(cow_file_size);
94 }
95
cow_file_size()96 uint64_t SnapshotMergeStats::cow_file_size() {
97 return report_.cow_file_size();
98 }
99
set_total_cow_size_bytes(uint64_t bytes)100 void SnapshotMergeStats::set_total_cow_size_bytes(uint64_t bytes) {
101 report_.set_total_cow_size_bytes(bytes);
102 }
103
set_estimated_cow_size_bytes(uint64_t bytes)104 void SnapshotMergeStats::set_estimated_cow_size_bytes(uint64_t bytes) {
105 report_.set_estimated_cow_size_bytes(bytes);
106 }
107
total_cow_size_bytes()108 uint64_t SnapshotMergeStats::total_cow_size_bytes() {
109 return report_.total_cow_size_bytes();
110 }
111
estimated_cow_size_bytes()112 uint64_t SnapshotMergeStats::estimated_cow_size_bytes() {
113 return report_.estimated_cow_size_bytes();
114 }
115
set_boot_complete_time_ms(uint32_t ms)116 void SnapshotMergeStats::set_boot_complete_time_ms(uint32_t ms) {
117 report_.set_boot_complete_time_ms(ms);
118 }
119
boot_complete_time_ms()120 uint32_t SnapshotMergeStats::boot_complete_time_ms() {
121 return report_.boot_complete_time_ms();
122 }
123
set_boot_complete_to_merge_start_time_ms(uint32_t ms)124 void SnapshotMergeStats::set_boot_complete_to_merge_start_time_ms(uint32_t ms) {
125 report_.set_boot_complete_to_merge_start_time_ms(ms);
126 }
127
boot_complete_to_merge_start_time_ms()128 uint32_t SnapshotMergeStats::boot_complete_to_merge_start_time_ms() {
129 return report_.boot_complete_to_merge_start_time_ms();
130 }
131
set_merge_failure_code(MergeFailureCode code)132 void SnapshotMergeStats::set_merge_failure_code(MergeFailureCode code) {
133 report_.set_merge_failure_code(code);
134 }
135
merge_failure_code()136 MergeFailureCode SnapshotMergeStats::merge_failure_code() {
137 return report_.merge_failure_code();
138 }
139
set_source_build_fingerprint(const std::string & fingerprint)140 void SnapshotMergeStats::set_source_build_fingerprint(const std::string& fingerprint) {
141 report_.set_source_build_fingerprint(fingerprint);
142 }
143
source_build_fingerprint()144 std::string SnapshotMergeStats::source_build_fingerprint() {
145 return report_.source_build_fingerprint();
146 }
147
148 class SnapshotMergeStatsResultImpl : public SnapshotMergeStats::Result {
149 public:
SnapshotMergeStatsResultImpl(const SnapshotMergeReport & report,std::chrono::steady_clock::duration merge_time)150 SnapshotMergeStatsResultImpl(const SnapshotMergeReport& report,
151 std::chrono::steady_clock::duration merge_time)
152 : report_(report), merge_time_(merge_time) {}
report() const153 const SnapshotMergeReport& report() const override { return report_; }
merge_time() const154 std::chrono::steady_clock::duration merge_time() const override { return merge_time_; }
155
156 private:
157 SnapshotMergeReport report_;
158 std::chrono::steady_clock::duration merge_time_;
159 };
160
Finish()161 std::unique_ptr<SnapshotMergeStats::Result> SnapshotMergeStats::Finish() {
162 if (!running_) {
163 LOG(ERROR) << "SnapshotMergeStats running_ == " << running_;
164 return nullptr;
165 }
166 running_ = false;
167
168 auto result = std::make_unique<SnapshotMergeStatsResultImpl>(
169 report_, std::chrono::steady_clock::now() - start_time_);
170
171 // We still want to report result if state is not deleted. Just leave
172 // it there and move on. A side effect is that it may be reported over and
173 // over again in the future, but there is nothing we can do.
174 (void)DeleteState();
175
176 return result;
177 }
178
179 } // namespace snapshot
180 } // namespace android
181