• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CPP_WATCHDOG_SERVER_SRC_UIDIOSTATS_H_
18 #define CPP_WATCHDOG_SERVER_SRC_UIDIOSTATS_H_
19 
20 #include <android-base/result.h>
21 #include <android-base/stringprintf.h>
22 #include <utils/Mutex.h>
23 #include <utils/RefBase.h>
24 
25 #include <stdint.h>
26 
27 #include <string>
28 #include <unordered_map>
29 
30 namespace android {
31 namespace automotive {
32 namespace watchdog {
33 
34 constexpr const char* kUidIoStatsPath = "/proc/uid_io/stats";
35 
36 enum UidState {
37     FOREGROUND = 0,
38     BACKGROUND,
39     UID_STATES,
40 };
41 
42 enum MetricType {
43     READ_BYTES = 0,  // bytes read (from storage layer)
44     WRITE_BYTES,     // bytes written (to storage layer)
45     FSYNC_COUNT,     // number of fsync syscalls
46     METRIC_TYPES,
47 };
48 
49 class IoUsage {
50 public:
IoUsage()51     IoUsage() : metrics{{0}} {};
IoUsage(int64_t fgRdBytes,int64_t bgRdBytes,int64_t fgWrBytes,int64_t bgWrBytes,int64_t fgFsync,int64_t bgFsync)52     IoUsage(int64_t fgRdBytes, int64_t bgRdBytes, int64_t fgWrBytes, int64_t bgWrBytes,
53             int64_t fgFsync, int64_t bgFsync) {
54         metrics[READ_BYTES][FOREGROUND] = fgRdBytes;
55         metrics[READ_BYTES][BACKGROUND] = bgRdBytes;
56         metrics[WRITE_BYTES][FOREGROUND] = fgWrBytes;
57         metrics[WRITE_BYTES][BACKGROUND] = bgWrBytes;
58         metrics[FSYNC_COUNT][FOREGROUND] = fgFsync;
59         metrics[FSYNC_COUNT][BACKGROUND] = bgFsync;
60     }
61     IoUsage& operator-=(const IoUsage& rhs);
62     bool operator==(const IoUsage& usage) const {
63         return memcmp(&metrics, &usage.metrics, sizeof(metrics)) == 0;
64     }
sumReadBytes()65     int64_t sumReadBytes() const {
66         const auto& [fgBytes, bgBytes] =
67                 std::tuple(metrics[READ_BYTES][FOREGROUND], metrics[READ_BYTES][BACKGROUND]);
68         return (std::numeric_limits<int64_t>::max() - fgBytes) > bgBytes
69                 ? (fgBytes + bgBytes)
70                 : std::numeric_limits<int64_t>::max();
71     }
sumWriteBytes()72     int64_t sumWriteBytes() const {
73         const auto& [fgBytes, bgBytes] =
74                 std::tuple(metrics[WRITE_BYTES][FOREGROUND], metrics[WRITE_BYTES][BACKGROUND]);
75         return (std::numeric_limits<int64_t>::max() - fgBytes) > bgBytes
76                 ? (fgBytes + bgBytes)
77                 : std::numeric_limits<int64_t>::max();
78     }
79     bool isZero() const;
80     std::string toString() const;
81     int64_t metrics[METRIC_TYPES][UID_STATES];
82 };
83 
84 struct UidIoUsage {
85     uid_t uid = 0;  // Linux user id.
86     IoUsage ios = {};
87     UidIoUsage& operator-=(const UidIoUsage& rhs) {
88         ios -= rhs.ios;
89         return *this;
90     }
91     bool operator==(const UidIoUsage& rhs) const { return uid == rhs.uid && ios == rhs.ios; }
toStringUidIoUsage92     std::string toString() const {
93         return android::base::StringPrintf("Uid: %d, Usage: {%s}", uid, ios.toString().c_str());
94     }
95 };
96 
97 class UidIoStats : public RefBase {
98 public:
99     explicit UidIoStats(const std::string& path = kUidIoStatsPath) :
100           kEnabled(!access(path.c_str(), R_OK)), kPath(path) {}
101 
~UidIoStats()102     virtual ~UidIoStats() {}
103 
104     // Collects the per-UID I/O usage.
105     virtual android::base::Result<void> collect();
106 
latestStats()107     virtual const std::unordered_map<uid_t, UidIoUsage> latestStats() const {
108         Mutex::Autolock lock(mMutex);
109         return mLatestUidIoUsages;
110     }
111 
deltaStats()112     virtual const std::unordered_map<uid_t, UidIoUsage> deltaStats() const {
113         Mutex::Autolock lock(mMutex);
114         return mDeltaUidIoUsages;
115     }
116 
117     // Returns true when the uid_io stats file is accessible. Otherwise, returns false.
118     // Called by IoPerfCollection and tests.
enabled()119     virtual bool enabled() { return kEnabled; }
120 
filePath()121     virtual std::string filePath() { return kPath; }
122 
123 private:
124     // Reads the contents of |kPath|.
125     android::base::Result<std::unordered_map<uid_t, UidIoUsage>> getUidIoUsagesLocked() const;
126 
127     // Makes sure only one collection is running at any given time.
128     mutable Mutex mMutex;
129 
130     // Latest dump from the file at |kPath|.
131     std::unordered_map<uid_t, UidIoUsage> mLatestUidIoUsages GUARDED_BY(mMutex);
132 
133     // Delta of per-UID I/O usage since last before collection.
134     std::unordered_map<uid_t, UidIoUsage> mDeltaUidIoUsages GUARDED_BY(mMutex);
135 
136     // True if kPath is accessible.
137     const bool kEnabled;
138 
139     // Path to uid_io stats file. Default path is |kUidIoStatsPath|.
140     const std::string kPath;
141 };
142 
143 }  // namespace watchdog
144 }  // namespace automotive
145 }  // namespace android
146 
147 #endif  //  CPP_WATCHDOG_SERVER_SRC_UIDIOSTATS_H_
148