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)87 void SnapshotMergeStats::set_state(android::snapshot::UpdateState state) {
88     report_.set_state(state);
89 }
90 
cow_file_size()91 uint64_t SnapshotMergeStats::cow_file_size() {
92     return report_.cow_file_size();
93 }
94 
total_cow_size_bytes()95 uint64_t SnapshotMergeStats::total_cow_size_bytes() {
96     return report_.total_cow_size_bytes();
97 }
98 
estimated_cow_size_bytes()99 uint64_t SnapshotMergeStats::estimated_cow_size_bytes() {
100     return report_.estimated_cow_size_bytes();
101 }
102 
set_boot_complete_time_ms(uint32_t ms)103 void SnapshotMergeStats::set_boot_complete_time_ms(uint32_t ms) {
104     report_.set_boot_complete_time_ms(ms);
105 }
106 
boot_complete_time_ms()107 uint32_t SnapshotMergeStats::boot_complete_time_ms() {
108     return report_.boot_complete_time_ms();
109 }
110 
set_boot_complete_to_merge_start_time_ms(uint32_t ms)111 void SnapshotMergeStats::set_boot_complete_to_merge_start_time_ms(uint32_t ms) {
112     report_.set_boot_complete_to_merge_start_time_ms(ms);
113 }
114 
boot_complete_to_merge_start_time_ms()115 uint32_t SnapshotMergeStats::boot_complete_to_merge_start_time_ms() {
116     return report_.boot_complete_to_merge_start_time_ms();
117 }
118 
set_merge_failure_code(MergeFailureCode code)119 void SnapshotMergeStats::set_merge_failure_code(MergeFailureCode code) {
120     report_.set_merge_failure_code(code);
121 }
122 
merge_failure_code()123 MergeFailureCode SnapshotMergeStats::merge_failure_code() {
124     return report_.merge_failure_code();
125 }
126 
set_source_build_fingerprint(const std::string & fingerprint)127 void SnapshotMergeStats::set_source_build_fingerprint(const std::string& fingerprint) {
128     report_.set_source_build_fingerprint(fingerprint);
129 }
130 
source_build_fingerprint()131 std::string SnapshotMergeStats::source_build_fingerprint() {
132     return report_.source_build_fingerprint();
133 }
134 
135 class SnapshotMergeStatsResultImpl : public SnapshotMergeStats::Result {
136   public:
SnapshotMergeStatsResultImpl(const SnapshotMergeReport & report,std::chrono::steady_clock::duration merge_time)137     SnapshotMergeStatsResultImpl(const SnapshotMergeReport& report,
138                                  std::chrono::steady_clock::duration merge_time)
139         : report_(report), merge_time_(merge_time) {}
report() const140     const SnapshotMergeReport& report() const override { return report_; }
merge_time() const141     std::chrono::steady_clock::duration merge_time() const override { return merge_time_; }
142 
143   private:
144     SnapshotMergeReport report_;
145     std::chrono::steady_clock::duration merge_time_;
146 };
147 
Finish()148 std::unique_ptr<SnapshotMergeStats::Result> SnapshotMergeStats::Finish() {
149     if (!running_) {
150         LOG(ERROR) << "SnapshotMergeStats running_ == " << running_;
151         return nullptr;
152     }
153     running_ = false;
154 
155     auto result = std::make_unique<SnapshotMergeStatsResultImpl>(
156             report_, std::chrono::steady_clock::now() - start_time_);
157 
158     // We still want to report result if state is not deleted. Just leave
159     // it there and move on. A side effect is that it may be reported over and
160     // over again in the future, but there is nothing we can do.
161     (void)DeleteState();
162 
163     return result;
164 }
165 
166 }  // namespace snapshot
167 }  // namespace android
168