• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021, 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 #ifndef CPP_WATCHDOG_SERVER_SRC_PROCDISKSTATS_H_
18 #define CPP_WATCHDOG_SERVER_SRC_PROCDISKSTATS_H_
19 
20 #include <android-base/result.h>
21 #include <android-base/stringprintf.h>
22 #include <android-base/strings.h>
23 #include <utils/Mutex.h>
24 #include <utils/RefBase.h>
25 
26 #include <string>
27 #include <unordered_set>
28 #include <vector>
29 
30 namespace android {
31 namespace automotive {
32 namespace watchdog {
33 
34 constexpr const char* kProcDiskStatsPath = "/proc/diskstats";
35 
recordStatsForDevice(const std::string & deviceName)36 inline constexpr bool recordStatsForDevice(const std::string& deviceName) {
37     for (const auto& prefix : {"zram", "ram"}) {
38         if (android::base::StartsWith(deviceName, prefix)) {
39             return false;
40         }
41     }
42     return true;
43 }
44 
45 // Struct that represents the stats from |kUidIoStatsPath|.
46 struct DiskStats {
47     int major = 0;
48     int minor = 0;
49     std::string deviceName;
50     uint64_t numReadsCompleted = 0;
51     uint64_t numReadsMerged = 0;
52     uint64_t numKibRead = 0;
53     uint64_t readTimeInMs = 0;
54     uint64_t numWritesCompleted = 0;
55     uint64_t numWritesMerged = 0;
56     uint64_t numKibWritten = 0;
57     uint64_t writeTimeInMs = 0;
58     uint64_t totalIoTimeInMs = 0;
59     uint64_t weightedTotalIoTimeInMs = 0;
60     uint64_t numFlushCompleted = 0;
61     uint64_t flushTimeInMs = 0;
62 
63     DiskStats& operator-=(const DiskStats& rhs);
64     DiskStats& operator+=(const DiskStats& rhs);
65     struct HashByPartition {
66         size_t operator()(const DiskStats& stats) const;
67     };
68     struct EqualByPartition {
69         bool operator()(const DiskStats& lhs, const DiskStats& rhs) const;
70     };
71 };
72 
73 /*
74  * Contains methods that should be implemented by the /proc/diskstats reader or any mock reader
75  * used in tests.
76  */
77 class IProcDiskStatsInterface : public android::RefBase {
78 public:
79     using PerPartitionDiskStats = ::std::unordered_set<DiskStats, DiskStats::HashByPartition,
80                                                        DiskStats::EqualByPartition>;
81 
82     // Collects the system-wide block devices statistics.
83     virtual android::base::Result<void> collect() = 0;
84 
85     // Returns the latest per-disk stats.
86     virtual PerPartitionDiskStats latestPerPartitionDiskStats() const = 0;
87 
88     // Returns the aggregated delta stats since the last before collection.
89     virtual DiskStats deltaSystemWideDiskStats() const = 0;
90 
91     // Returns true when the proc diskstats file is accessible. Otherwise, returns false.
92     virtual bool enabled() const = 0;
93 
94     // Path to the disk stats file.
95     virtual std::string filePath() const = 0;
96 };
97 
98 class ProcDiskStats : public IProcDiskStatsInterface {
99 public:
100     explicit ProcDiskStats(const std::string& path = kProcDiskStatsPath) :
101           kEnabled(!access(path.c_str(), R_OK)),
102           kPath(path) {}
103 
~ProcDiskStats()104     ~ProcDiskStats() {}
105 
106     android::base::Result<void> collect();
107 
latestPerPartitionDiskStats()108     PerPartitionDiskStats latestPerPartitionDiskStats() const {
109         Mutex::Autolock lock(mMutex);
110         return mLatestPerPartitionDiskStats;
111     }
112 
deltaSystemWideDiskStats()113     DiskStats deltaSystemWideDiskStats() const {
114         Mutex::Autolock lock(mMutex);
115         return mDeltaSystemWideDiskStats;
116     }
117 
enabled()118     bool enabled() const { return kEnabled; }
119 
filePath()120     std::string filePath() const { return kPath; }
121 
122 private:
123     // Makes sure only one collection is running at any given time.
124     mutable Mutex mMutex;
125 
126     // Delta of per-UID I/O usage since last before collection.
127     DiskStats mDeltaSystemWideDiskStats GUARDED_BY(mMutex);
128 
129     /*
130      * Latest per-disk stats from the file at |kPath|. Per-disk stats is required for calculating
131      * per-disk delta since last collection. Because the stats reported in |kPath| may overflow,
132      * storing the stats per-disk helps to deal with this issue.
133      */
134     PerPartitionDiskStats mLatestPerPartitionDiskStats GUARDED_BY(mMutex);
135 
136     // True if |kPath| is accessible.
137     const bool kEnabled;
138 
139     // Path to disk stats file.
140     const std::string kPath;
141 };
142 
143 }  // namespace watchdog
144 }  // namespace automotive
145 }  // namespace android
146 
147 #endif  //  CPP_WATCHDOG_SERVER_SRC_PROCDISKSTATS_H_
148